Successfully reported this slideshow.
Your SlideShare is downloading. ×

Testing sucks

Loading in …3
×

Check these out next

1 of 139 Ad
1 of 139 Ad
Advertisement

More Related Content

Advertisement

Testing sucks

  1. 1. Testing Sucks Leo Balter - BrazilJS 2012 JS
  2. 2. Testar é chato!
  3. 3. Testes vs Testar!
  4. 4. Testes humanos • Repetitivos • Estressantes • Cansativos
  5. 5. Concentração polarizada • Nos concentramos em um único ponto • Não vemos os demais • falsa sensação de segurança
  6. 6. Olhar Viciado
  7. 7. Testes de Trollagem
  8. 8. Pare de “ficar testando” seu código
  9. 9. JSHint/JSLint não testa código! • Convenção de estilo • Erros comuns • “As Boas Partes”
  10. 10. Mito do Compilador
  11. 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. 12. Aplicação não testada
  13. 13. A Síndrome do “o que está funcionando não se deve mexer”.
  14. 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. 15. Acredite: Sua aplicação vai falhar!
  16. 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. 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. 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. 19. Alto Ri sc o C Ri rí t sc ico o de Ocorrê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. 20. Automatização • --Retrabalho • --Surpresas • Mais tempo para o que é interessante • Menos tempo para testar tudo novamente
  21. 21. Automatização • --Retrabalho • --Surpresas • Mais tempo para o que é interessante • Menos tempo para testar tudo novamente
  22. 22. Metodologias Ágeis • Aplicar testes é uma rotina contida em Metodologias Ágeis • Testes não dependem de metodologias ágeis • Ex.: jQuery
  23. 23. Funciona Faz o que deveria
  24. 24. Esse código funciona! • Um código pode funcionar perfeitamente • Estar 100% testado • e não cumprir 10% do seu papel
  25. 25. Fluxo
  26. 26. Especificação Fluxo
  27. 27. Especificação Plano de Testes Fluxo
  28. 28. Especificação Plano de Testes Fluxo Testes
  29. 29. Validação
  30. 30. Validação Plano de Testes
  31. 31. Validação Plano de Testes Especificação
  32. 32. Validação Plano de Testes Testes Especificação
  33. 33. Validação Plano de Testes Testes Especificação Aplicação
  34. 34. Testes não validam especificação! Testes não criam especificação!
  35. 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. 36. Teste que Falha Código Refatorar Baby Steps (Testes Unitários)
  37. 37. Sempre em Baby Steps • Ótimo para pegar o ritmo • função 1, 2, 3, pin • Treino do Lutador
  38. 38. Cobertura de Código
  39. 39. function foo( bar ) { if ( bar ) { console.log( 'yes!' ); else { console.log( 'no!' ); } }
  40. 40. function foo( bar ) { if ( bar ) { console.log( 'yes!' ); else { console.log( 'no!' ); } }
  41. 41. function foo( bar ) { if ( bar ) { console.log( 'yes!' ); else { console.log( 'no!' ); } }
  42. 42. function foo( bar ) { if ( bar ) { console.log( 'yes!' ); else { console.log( 'no!' ); } }
  43. 43. function foo( bar ) { if ( bar ) { console.log( 'yes!' ); else { console.log( 'no!' ); } }
  44. 44. function foo( bar ) { if ( bar ) { console.log( 'yes!' ); else { console.log( 'no!' ); } }
  45. 45. Código 100% coberto por testes!
  46. 46. • JSCoverage • CoverJS
  47. 47. Tudo é testável • Complexidade vs Criticidade • window.location.replace()
  48. 48. JS Testes em JavaScript
  49. 49. Testes Unitários Interface Funcionais Desempenho Integração
  50. 50. Open Web vários ambientes
  51. 51. Firefox Chrome Opera IE 8, 9[, 10, ...]
  52. 52. Firefox Chrome Mobile Opera IE 8, 9[, 10, ...]
  53. 53. PhantomJS Webkit
  54. 54. Ferramentas QUnit NodeUnit Mocha Vows Jasmine
  55. 55. Estilos de Testes TDD BDD Exports
  56. 56. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  57. 57. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  58. 58. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  59. 59. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  60. 60. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  61. 61. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  62. 62. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  63. 63. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  64. 64. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  65. 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. 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. 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. 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. 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. 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. 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. 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. 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. 74. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  75. 75. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  76. 76. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  77. 77. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  78. 78. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  79. 79. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  80. 80. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  81. 81. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  82. 82. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  83. 83. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  84. 84. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  85. 85. Como começar?
  86. 86. HTML Estático JavaScript Testes
  87. 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. 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. 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. 90. DexterJS
  91. 91. Dexter.spy
  92. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 111. Dexter.stub
  112. 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. 113. test( 'stubbed carly()', 1, function() { var stub = Dexter.stub( window, 'carly', function() { return 'relax'; }); equal( meSad( true ), 'relax', 'stubbed carly!' ); stub.restore(); });
  114. 114. test( 'stubbed carly()', 1, function() { var stub = Dexter.stub( window, 'carly', function() { return 'relax'; }); equal( meSad( true ), 'relax', 'stubbed carly!' ); stub.restore(); });
  115. 115. test( 'stubbed carly()', 1, function() { var stub = Dexter.stub( window, 'carly', function() { return 'relax'; }); equal( meSad( true ), 'relax', 'stubbed carly!' ); stub.restore(); });
  116. 116. test( 'stubbed carly()', 1, function() { var stub = Dexter.stub( window, 'carly', function() { return 'relax'; }); equal( meSad( true ), 'relax', 'stubbed carly!' ); stub.restore(); });
  117. 117. test( 'stubbed carly()', 1, function() { var stub = Dexter.stub( window, 'carly', function() { return 'relax'; }); equal( meSad( true ), 'relax', 'stubbed carly!' ); stub.restore(); });
  118. 118. test( 'stubbed carly()', 1, function() { var stub = Dexter.stub( window, 'carly', function() { return 'relax'; }); equal( meSad( true ), 'relax', 'stubbed carly!' ); stub.restore(); });
  119. 119. test( 'stubbed carly()', 1, function() { var stub = Dexter.stub( window, 'carly', function() { return 'relax'; }); equal( meSad( true ), 'relax', 'stubbed carly!' ); stub.restore(); });
  120. 120. Dexter.fakeXHR
  121. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 132. Começar a criar testes?
  133. 133. Experimente!
  134. 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. 135. Obrigado! @leobalter leo@balter.com.br JS http://search.cpan.org/~leobalter/ • @garu_rj • @blabos • @aoqfonseca

×