Your SlideShare is downloading. ×

Testing sucks

912
views

Published on

Presentation given in BrazilJS 2012

Presentation given in BrazilJS 2012

Published in: Technology, Business

2 Comments
7 Likes
Statistics
Notes
No Downloads
Views
Total Views
912
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
20
Comments
2
Likes
7
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Testing Sucks Leo Balter - BrazilJS 2012 JS
  • 2. Testar é chato!
  • 3. Testes vs Testar!
  • 4. Testes humanos • Repetitivos • Estressantes • Cansativos
  • 5. Concentração polarizada• Nos concentramos em um único ponto• Não vemos os demais• falsa sensação de segurança
  • 6. OlharViciado
  • 7. Testes de Trollagem
  • 8. Pare de “ficar testando” seu código
  • 9. JSHint/JSLint não testa código!• Convenção de estilo• Erros comuns• “As Boas Partes”
  • 10. Mito doCompilador
  • 11. Pânico vs Benefícios• Muito fácil criar testes para algo que ainda não existe• Não tão simples quando a aplicação já existe e está “no ar”.
  • 12. Aplicaçãonão testada
  • 13. A Síndrome do “o que estáfuncionando nãose deve mexer”.
  • 14. Quebre a aplicação!• Criamos testes simples que passem• Teste o que está em produção• Cobertura de testes• O que é crítico?• Especificação• O que falta testar?• Testes de Trollagem
  • 15. Acredite:Sua aplicação vai falhar!
  • 16. Já viu essa síndrome?• Não vai ao médico pra evitar descobrir um mal grave• Pode haver um problema latente que vai falhar em um momento crítico• Pode acabar em morte
  • 17. Na aplicação• Não testamos para não descobrir o que falha• Há problemas latentes que vão falhar em momentos críticos (Por exemplo: um sistema de pagamento do seu e-commerce)• Sua empresa morre (vai a falência)
  • 18. Estabeleça o que é crítico• Quão crítico é cada parte do seu sistema?• Se não funcionar, quais as consequências?
  • 19. Alto Ri sc o C Ri rí t sc ico o deOcorrência Ri ní sc ve o ml de éd ba io ix o ní ve Baixo l Baixo Impacto Alto Gerenciamento de Risco http://bit.ly/11tTwN
  • 20. Automatização• --Retrabalho• --Surpresas• Mais tempo para o que é interessante• Menos tempo para testar tudo novamente
  • 21. Automatização• --Retrabalho• --Surpresas• Mais tempo para o que é interessante• Menos tempo para testar tudo novamente
  • 22. Metodologias Ágeis• Aplicar testes é uma rotina contida em Metodologias Ágeis• Testes não dependem de metodologias ágeis• Ex.: jQuery
  • 23. FuncionaFaz o que deveria
  • 24. Esse código funciona! • Um código pode funcionar perfeitamente • Estar 100% testado • e não cumprir 10% do seu papel
  • 25. Fluxo
  • 26. EspecificaçãoFluxo
  • 27. Especificação Plano de TestesFluxo
  • 28. Especificação Plano de TestesFluxo Testes
  • 29. Validação
  • 30. ValidaçãoPlano de Testes
  • 31. ValidaçãoPlano de Testes Especificação
  • 32. ValidaçãoPlano de Testes Testes Especificação
  • 33. ValidaçãoPlano de Testes Testes Especificação Aplicação
  • 34. Testes não validam especificação!Testes não criam especificação!
  • 35. Testes vs Especificação• Se os testes validassem especificação, não poderiamos prever correções de bugs e comportamentos de ambientes.• Bugs não fazem parte de uma especificação.
  • 36. Teste que Falha Código Refatorar Baby Steps (Testes Unitários)
  • 37. Sempre em Baby Steps• Ótimo para pegar o ritmo• função 1, 2, 3, pin• Treino do Lutador
  • 38. Cobertura de Código
  • 39. function foo( bar ) { if ( bar ) { console.log( yes! ); else { console.log( no! ); }}
  • 40. function foo( bar ) { if ( bar ) { console.log( yes! ); else { console.log( no! ); }}
  • 41. function foo( bar ) { if ( bar ) { console.log( yes! ); else { console.log( no! ); }}
  • 42. function foo( bar ) { if ( bar ) { console.log( yes! ); else { console.log( no! ); }}
  • 43. function foo( bar ) { if ( bar ) { console.log( yes! ); else { console.log( no! ); }}
  • 44. function foo( bar ) { if ( bar ) { console.log( yes! ); else { console.log( no! ); }}
  • 45. Código 100% coberto por testes!
  • 46. • JSCoverage• CoverJS
  • 47. Tudo é testável• Complexidade vs Criticidade• window.location.replace()
  • 48. JSTestes em JavaScript
  • 49. Testes UnitáriosInterface FuncionaisDesempenho Integração
  • 50. Open Webvários ambientes
  • 51. FirefoxChrome Opera IE 8, 9[, 10, ...]
  • 52. FirefoxChrome Mobile Opera IE 8, 9[, 10, ...]
  • 53. PhantomJS Webkit
  • 54. Ferramentas QUnit NodeUnitMocha Vows Jasmine
  • 55. Estilos de TestesTDD BDD Exports
  • 56. TDDmodule( "Basics" );test( "hello test", function() {  ok( 1 == "1", "Passed!" );}); http://qunitjs.com/
  • 57. TDDmodule( "Basics" );test( "hello test", function() {  ok( 1 == "1", "Passed!" );}); http://qunitjs.com/
  • 58. TDDmodule( "Basics" );test( "hello test", function() {  ok( 1 == "1", "Passed!" );}); http://qunitjs.com/
  • 59. TDDmodule( "Basics" );test( "hello test", function() {  ok( 1 == "1", "Passed!" );}); http://qunitjs.com/
  • 60. TDDmodule( "Basics" );test( "hello test", function() {  ok( 1 == "1", "Passed!" );}); http://qunitjs.com/
  • 61. TDDmodule( "Basics" );test( "hello test", function() {  ok( 1 == "1", "Passed!" );}); http://qunitjs.com/
  • 62. TDDmodule( "Basics" );test( "hello test", function() {  ok( 1 == "1", "Passed!" );}); http://qunitjs.com/
  • 63. TDDmodule( "Basics" );test( "hello test", function() {  ok( 1 == "1", "Passed!" );}); http://qunitjs.com/
  • 64. TDDmodule( "Basics" );test( "hello test", function() {  ok( 1 == "1", "Passed!" );}); http://qunitjs.com/
  • 65. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 66. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 67. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 68. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 69. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 70. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 71. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 72. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 73. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 74. BDDdescribe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); });});
  • 75. BDDdescribe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); });});
  • 76. BDDdescribe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); });});
  • 77. BDDdescribe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); });});
  • 78. BDDdescribe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); });});
  • 79. BDDdescribe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); });});
  • 80. Exportsmodule.exports = { test1: function (test) { test.equals(this.foo, bar); test.done(); }};
  • 81. Exportsmodule.exports = { test1: function (test) { test.equals(this.foo, bar); test.done(); }};
  • 82. Exportsmodule.exports = { test1: function (test) { test.equals(this.foo, bar); test.done(); }};
  • 83. Exportsmodule.exports = { test1: function (test) { test.equals(this.foo, bar); test.done(); }};
  • 84. Exportsmodule.exports = { test1: function (test) { test.equals(this.foo, bar); test.done(); }};
  • 85. Comocomeçar?
  • 86. HTML Estático JavaScript Testes
  • 87. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <div id="qunit-fixtures"> <div id="foo">bar</div> </div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 88. <!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>QUnit Example</title>  <link rel="stylesheet" href="/t/qunit.css"></head><body>  <div id="qunit"></div>  <div id="qunit-fixtures"> <div id="foo">bar</div> </div>  <script src="/t/qunit.js"></script> <script src="/js/script.js"></script>  <script src="/t/unit/tests.js"></script></body></html>
  • 89. Código testado tem bom desempenho?• Testes unitários não medem desempenho• Existem testes de desempenho• Código sem erros pode evitar lentidão
  • 90. DexterJS
  • 91. Dexter.spy
  • 92. function carly( crazy ) { if ( typeof ( crazy ) === number ) { return Call me maybe?; } else { return Hey, I just met you!, and this is + crazy; }}function meSad( maybe ) { return carly( maybe ? 5555555 : crazy! );} http://jsbin.com/osijuq/7/edit
  • 93. function carly( crazy ) { if ( typeof ( crazy ) === number ) { return Call me maybe?; } else { return Hey, I just met you!, and this is + crazy; }}function meSad( maybe ) { return carly( maybe ? 5555555 : crazy! );} http://jsbin.com/osijuq/7/edit
  • 94. function carly( crazy ) { if ( typeof ( crazy ) === number ) { return Call me maybe?; } else { return Hey, I just met you!, and this is + crazy; }}function meSad( maybe ) { return carly( maybe ? 5555555 : crazy! );} http://jsbin.com/osijuq/7/edit
  • 95. function carly( crazy ) { if ( typeof ( crazy ) === number ) { return Call me maybe?; } else { return Hey, I just met you!, and this is + crazy; }}function meSad( maybe ) { return carly( maybe ? 5555555 : crazy! );} http://jsbin.com/osijuq/7/edit
  • 96. function carly( crazy ) { if ( typeof ( crazy ) === number ) { return Call me maybe?; } else { return Hey, I just met you!, and this is + crazy; }}function meSad( maybe ) { return carly( maybe ? 5555555 : crazy! );} http://jsbin.com/osijuq/7/edit
  • 97. function carly( crazy ) { if ( typeof ( crazy ) === number ) { return Call me maybe?; } else { return Hey, I just met you!, and this is + crazy; }}function meSad( maybe ) { return carly( maybe ? 5555555 : crazy! );} http://jsbin.com/osijuq/7/edit
  • 98. function carly( crazy ) { if ( typeof ( crazy ) === number ) { return Call me maybe?; } else { return Hey, I just met you!, and this is + crazy; }}function meSad( maybe ) { return carly( maybe ? 5555555 : crazy! );} http://jsbin.com/osijuq/7/edit
  • 99. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 100. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 101. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 102. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 103. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 104. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 105. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 106. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 107. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 108. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 109. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 110. test( carly(), 4, function() { var spy = Dexter.spy( window, carly, function( arg1 ) { equal( arg1, crazy!, me sad got crazy! ); }); meSad( false ); equal( spy.called, 1, carly was called once ); spy.callback = 0; equal( meSad( true ), Call me maybe?, keep asking ); equal( spy.called, 2, carly called again! ); spy.restore();});
  • 111. Dexter.stub
  • 112. function carly( crazy ) { if ( typeof ( crazy ) === number ) { return Call me maybe?; } else { return Hey, I just met you!, and this is + crazy; }}function meSad( maybe ) { return carly( maybe ? 5555555 : crazy! );}
  • 113. test( stubbed carly(), 1, function() { var stub = Dexter.stub( window, carly, function() { return relax; }); equal( meSad( true ), relax, stubbed carly! ); stub.restore();});
  • 114. test( stubbed carly(), 1, function() { var stub = Dexter.stub( window, carly, function() { return relax; }); equal( meSad( true ), relax, stubbed carly! ); stub.restore();});
  • 115. test( stubbed carly(), 1, function() { var stub = Dexter.stub( window, carly, function() { return relax; }); equal( meSad( true ), relax, stubbed carly! ); stub.restore();});
  • 116. test( stubbed carly(), 1, function() { var stub = Dexter.stub( window, carly, function() { return relax; }); equal( meSad( true ), relax, stubbed carly! ); stub.restore();});
  • 117. test( stubbed carly(), 1, function() { var stub = Dexter.stub( window, carly, function() { return relax; }); equal( meSad( true ), relax, stubbed carly! ); stub.restore();});
  • 118. test( stubbed carly(), 1, function() { var stub = Dexter.stub( window, carly, function() { return relax; }); equal( meSad( true ), relax, stubbed carly! ); stub.restore();});
  • 119. test( stubbed carly(), 1, function() { var stub = Dexter.stub( window, carly, function() { return relax; }); equal( meSad( true ), relax, stubbed carly! ); stub.restore();});
  • 120. Dexter.fakeXHR
  • 121. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 122. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 123. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 124. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 125. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 126. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 127. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 128. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 129. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 130. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 131. test( a fakeXHR, 2, function() { var fakeXHR = Dexter.fakeXHR(); $.get( /ajax.url, function() { ok( true, ajax completed ); }); equal( fakeXHR.requests.length, 1, requests === 1 ); fakeXHR.respond({ body : this is the ajax returned text, headers : { foo2 : bar2 }, status : 200 });});
  • 132. Começar a criar testes?
  • 133. Experimente!
  • 134. Referências• Coding Dojo• Inicialize um projeto com o GruntJS• TDD - Kent Back• Engenharia de Software - Roger S Pressman• Testable JavaScript - Mark Ethan Trostler *
  • 135. Obrigado! @leobalter leo@balter.com.br JShttp://search.cpan.org/~leobalter/ • @garu_rj • @blabos • @aoqfonseca

×