SlideShare a Scribd company logo
1 of 139
Download to read offline
Testing Sucks
 Leo Balter - BrazilJS 2012
                              JS
Testar é chato!
Testes vs Testar!
Testes humanos
         • Repetitivos
         • Estressantes
         • Cansativos
Concentração
    polarizada
• Nos concentramos em um único ponto
• Não vemos os demais
• falsa sensação de segurança
Olhar
Viciado
Testes de Trollagem
Pare de “ficar testando”
      seu código
JSHint/JSLint não testa
           código!


• Convenção de estilo
• Erros comuns
• “As Boas Partes”
Mito do
Compilador
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”.
Aplicação
não testada
A Síndrome do
   “o que está
funcionando não
se deve mexer”.
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
Acredite:
Sua aplicação vai falhar!
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
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)
Estabeleça o que é
         crítico

• Quão crítico é cada parte do seu sistema?
• Se não funcionar, quais as consequências?
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
Automatização



• --Retrabalho
• --Surpresas
• Mais tempo para o que é interessante
• Menos tempo para testar tudo novamente
Automatização



• --Retrabalho
• --Surpresas
• Mais tempo para o que é interessante
• Menos tempo para testar tudo novamente
Metodologias Ágeis
• Aplicar testes é uma rotina contida em
  Metodologias Ágeis
• Testes não dependem de metodologias ágeis
• Ex.: jQuery
Funciona


Faz o que deveria
Esse código funciona!
            • Um código pode
              funcionar
              perfeitamente
            • Estar 100% testado
            • e não cumprir 10%
              do seu papel
Fluxo
Especificação




Fluxo
Especificação




                Plano de Testes




Fluxo
Especificação




                Plano de Testes




Fluxo                             Testes
Validação
Validação
Plano de Testes
Validação
Plano de Testes




 Especificação
Validação
Plano de Testes   Testes




 Especificação
Validação
Plano de Testes    Testes




 Especificação     Aplicação
Testes não validam
  especificação!
Testes não criam
 especificação!
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.
Teste que Falha        Código          Refatorar




             Baby Steps
                  (Testes Unitários)
Sempre em Baby Steps

• Ótimo para pegar o ritmo
• função 1, 2, 3, pin
• Treino do Lutador
Cobertura
   de
 Código
function foo( bar ) {
  if ( bar ) {
    console.log( 'yes!' );
  else {
    console.log( 'no!' );
  }
}
function foo( bar ) {
  if ( bar ) {
    console.log( 'yes!' );
  else {
    console.log( 'no!' );
  }
}
function foo( bar ) {
  if ( bar ) {
    console.log( 'yes!' );
  else {
    console.log( 'no!' );
  }
}
function foo( bar ) {
  if ( bar ) {
    console.log( 'yes!' );
  else {
    console.log( 'no!' );
  }
}
function foo( bar ) {
  if ( bar ) {
    console.log( 'yes!' );
  else {
    console.log( 'no!' );
  }
}
function foo( bar ) {
  if ( bar ) {
    console.log( 'yes!' );
  else {
    console.log( 'no!' );
  }
}
Código 100% coberto
     por testes!
• JSCoverage
• CoverJS
Tudo é testável


• Complexidade vs Criticidade
• window.location.replace()
JS
Testes em JavaScript
Testes

            Unitários
Interface           Funcionais

Desempenho         Integração
Open Web




vários ambientes
Firefox

Chrome                        Opera

         IE 8, 9[, 10, ...]
Firefox

Chrome       Mobile           Opera

         IE 8, 9[, 10, ...]
PhantomJS




       Webkit
Ferramentas

 QUnit     NodeUnit

Mocha    Vows   Jasmine
Estilos de Testes


TDD   BDD   Exports
TDD
module( "Basics" );

test( "hello test", function() {
  ok( 1 == "1", "Passed!" );
});




          http://qunitjs.com/
TDD
module( "Basics" );

test( "hello test", function() {
  ok( 1 == "1", "Passed!" );
});




          http://qunitjs.com/
TDD
module( "Basics" );

test( "hello test", function() {
  ok( 1 == "1", "Passed!" );
});




          http://qunitjs.com/
TDD
module( "Basics" );

test( "hello test", function() {
  ok( 1 == "1", "Passed!" );
});




          http://qunitjs.com/
TDD
module( "Basics" );

test( "hello test", function() {
  ok( 1 == "1", "Passed!" );
});




          http://qunitjs.com/
TDD
module( "Basics" );

test( "hello test", function() {
  ok( 1 == "1", "Passed!" );
});




          http://qunitjs.com/
TDD
module( "Basics" );

test( "hello test", function() {
  ok( 1 == "1", "Passed!" );
});




          http://qunitjs.com/
TDD
module( "Basics" );

test( "hello test", function() {
  ok( 1 == "1", "Passed!" );
});




          http://qunitjs.com/
TDD
module( "Basics" );

test( "hello test", function() {
  ok( 1 == "1", "Passed!" );
});




          http://qunitjs.com/
<!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>
<!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>
<!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>
<!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>
<!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>
<!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>
<!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>
<!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>
<!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>
BDD

describe("A suite", function() {
  it("spec with an expectation",
      function(){
       expect(true).toBe(true);
      });
});
BDD

describe("A suite", function() {
  it("spec with an expectation",
      function(){
       expect(true).toBe(true);
      });
});
BDD

describe("A suite", function() {
  it("spec with an expectation",
      function(){
       expect(true).toBe(true);
      });
});
BDD

describe("A suite", function() {
  it("spec with an expectation",
      function(){
       expect(true).toBe(true);
      });
});
BDD

describe("A suite", function() {
  it("spec with an expectation",
      function(){
       expect(true).toBe(true);
      });
});
BDD

describe("A suite", function() {
  it("spec with an expectation",
      function(){
       expect(true).toBe(true);
      });
});
Exports

module.exports = {
     test1: function (test) {
         test.equals(this.foo, 'bar');
         test.done();
     }
};
Exports

module.exports = {
     test1: function (test) {
         test.equals(this.foo, 'bar');
         test.done();
     }
};
Exports

module.exports = {
     test1: function (test) {
         test.equals(this.foo, 'bar');
         test.done();
     }
};
Exports

module.exports = {
     test1: function (test) {
         test.equals(this.foo, 'bar');
         test.done();
     }
};
Exports

module.exports = {
     test1: function (test) {
         test.equals(this.foo, 'bar');
         test.done();
     }
};
Como
começar?
HTML Estático
  JavaScript
    Testes
<!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>
<!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>
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
DexterJS
Dexter.spy
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
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
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
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
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
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
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
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();
});
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();
});
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();
});
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();
});
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();
});
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();
});
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();
});
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();
});
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();
});
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();
});
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();
});
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();
});
Dexter.stub
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!' );
}
test( 'stubbed carly()', 1, function() {
  var stub = Dexter.stub( window, 'carly', function() {
    return 'relax';
  });

  equal( meSad( true ), 'relax', 'stubbed carly!' );

  stub.restore();
});
test( 'stubbed carly()', 1, function() {
  var stub = Dexter.stub( window, 'carly', function() {
    return 'relax';
  });

  equal( meSad( true ), 'relax', 'stubbed carly!' );

  stub.restore();
});
test( 'stubbed carly()', 1, function() {
  var stub = Dexter.stub( window, 'carly', function() {
    return 'relax';
  });

  equal( meSad( true ), 'relax', 'stubbed carly!' );

  stub.restore();
});
test( 'stubbed carly()', 1, function() {
  var stub = Dexter.stub( window, 'carly', function() {
    return 'relax';
  });

  equal( meSad( true ), 'relax', 'stubbed carly!' );

  stub.restore();
});
test( 'stubbed carly()', 1, function() {
  var stub = Dexter.stub( window, 'carly', function() {
    return 'relax';
  });

  equal( meSad( true ), 'relax', 'stubbed carly!' );

  stub.restore();
});
test( 'stubbed carly()', 1, function() {
  var stub = Dexter.stub( window, 'carly', function() {
    return 'relax';
  });

  equal( meSad( true ), 'relax', 'stubbed carly!' );

  stub.restore();
});
test( 'stubbed carly()', 1, function() {
  var stub = Dexter.stub( window, 'carly', function() {
    return 'relax';
  });

  equal( meSad( true ), 'relax', 'stubbed carly!' );

  stub.restore();
});
Dexter.fakeXHR
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
      });
});
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
      });
});
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
      });
});
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
      });
});
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
      });
});
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
      });
});
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
      });
});
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
      });
});
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
      });
});
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
      });
});
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
      });
});
Começar a criar testes?
Experimente!
Referências
• Coding Dojo
• Inicialize um projeto com o GruntJS
• TDD - Kent Back
• Engenharia de Software - Roger S Pressman
• Testable JavaScript - Mark Ethan Trostler *
Obrigado!
            @leobalter
        leo@balter.com.br
                                         JS
http://search.cpan.org/~leobalter/
                                     •   @garu_rj

                                     •   @blabos

                                     •   @aoqfonseca

More Related Content

What's hot

Atividades de Teste e Cobertura de Código em Java
Atividades de Teste e Cobertura de Código em JavaAtividades de Teste e Cobertura de Código em Java
Atividades de Teste e Cobertura de Código em Javaaceiro
 
Introdução a testes unitários com jUnit
Introdução a testes unitários com jUnitIntrodução a testes unitários com jUnit
Introdução a testes unitários com jUnitLeonardo Soares
 
Treinamento Testes Unitários - parte 1
Treinamento Testes Unitários - parte 1Treinamento Testes Unitários - parte 1
Treinamento Testes Unitários - parte 1Diego Pacheco
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Androidtdc-globalcode
 
Teste de Integração - Unidade III
Teste de Integração - Unidade IIITeste de Integração - Unidade III
Teste de Integração - Unidade IIIJoão Lourenço
 
Teste unitário
Teste unitárioTeste unitário
Teste unitáriodist_bp
 
Android: testes automatizados e TDD
Android: testes automatizados e TDDAndroid: testes automatizados e TDD
Android: testes automatizados e TDDDextra
 
Testes Automatizados de Software
Testes Automatizados de SoftwareTestes Automatizados de Software
Testes Automatizados de SoftwareMaurício Aniche
 
Validação e Testes de Software - MOD2
Validação e Testes de Software - MOD2Validação e Testes de Software - MOD2
Validação e Testes de Software - MOD2Fernando Palma
 
Certificação Java: Exceções
Certificação Java: ExceçõesCertificação Java: Exceções
Certificação Java: ExceçõesEduardo Mendes
 
Apresentacao Testes de Unidade
Apresentacao Testes de UnidadeApresentacao Testes de Unidade
Apresentacao Testes de UnidadeAline Ferreira
 

What's hot (19)

Testes Unitários
Testes UnitáriosTestes Unitários
Testes Unitários
 
Atividades de Teste e Cobertura de Código em Java
Atividades de Teste e Cobertura de Código em JavaAtividades de Teste e Cobertura de Código em Java
Atividades de Teste e Cobertura de Código em Java
 
Introdução a testes unitários com jUnit
Introdução a testes unitários com jUnitIntrodução a testes unitários com jUnit
Introdução a testes unitários com jUnit
 
Treinamento Testes Unitários - parte 1
Treinamento Testes Unitários - parte 1Treinamento Testes Unitários - parte 1
Treinamento Testes Unitários - parte 1
 
Clean code
Clean codeClean code
Clean code
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
 
Testes de Integração
Testes de IntegraçãoTestes de Integração
Testes de Integração
 
Teste de Integração - Unidade III
Teste de Integração - Unidade IIITeste de Integração - Unidade III
Teste de Integração - Unidade III
 
Teste unitário
Teste unitárioTeste unitário
Teste unitário
 
Android: testes automatizados e TDD
Android: testes automatizados e TDDAndroid: testes automatizados e TDD
Android: testes automatizados e TDD
 
Testes Automatizados de Software
Testes Automatizados de SoftwareTestes Automatizados de Software
Testes Automatizados de Software
 
Validação e Testes de Software - MOD2
Validação e Testes de Software - MOD2Validação e Testes de Software - MOD2
Validação e Testes de Software - MOD2
 
Testes de Sistema
Testes de SistemaTestes de Sistema
Testes de Sistema
 
Certificação Java: Exceções
Certificação Java: ExceçõesCertificação Java: Exceções
Certificação Java: Exceções
 
TDD com Python
TDD com PythonTDD com Python
TDD com Python
 
TDD com Python (Completo)
TDD com Python (Completo)TDD com Python (Completo)
TDD com Python (Completo)
 
Java 12
Java 12Java 12
Java 12
 
Junit 4.0
Junit 4.0Junit 4.0
Junit 4.0
 
Apresentacao Testes de Unidade
Apresentacao Testes de UnidadeApresentacao Testes de Unidade
Apresentacao Testes de Unidade
 

Similar to Testing Sucks - Why and How to Test JS Code

Test é para os fracos
Test é para os fracosTest é para os fracos
Test é para os fracosThiago Avelino
 
Samanta Cicilia - MTC - Importância de Testes Automatizados para Continuous D...
Samanta Cicilia - MTC - Importância de Testes Automatizados para Continuous D...Samanta Cicilia - MTC - Importância de Testes Automatizados para Continuous D...
Samanta Cicilia - MTC - Importância de Testes Automatizados para Continuous D...minastestingconference
 
Importância de Testes Automatizados para Continuous Delivery & DevOps
Importância de Testes Automatizados para Continuous Delivery & DevOpsImportância de Testes Automatizados para Continuous Delivery & DevOps
Importância de Testes Automatizados para Continuous Delivery & DevOpsSamanta Cicilia
 
PHPUnit e teste de software
PHPUnit e teste de softwarePHPUnit e teste de software
PHPUnit e teste de softwarericardophp
 
Introdução ao Teste de Software - Uma abordagem prática
Introdução ao Teste de Software - Uma abordagem práticaIntrodução ao Teste de Software - Uma abordagem prática
Introdução ao Teste de Software - Uma abordagem práticaFabrício Campos
 
Paletra sobre TDD, ocorrida no #DevDojo
Paletra sobre TDD, ocorrida no #DevDojoPaletra sobre TDD, ocorrida no #DevDojo
Paletra sobre TDD, ocorrida no #DevDojoflavio1110
 
TDC 2014 POA - Clean Code para Testers
TDC 2014 POA - Clean Code para TestersTDC 2014 POA - Clean Code para Testers
TDC 2014 POA - Clean Code para TestersStefan Teixeira
 
[DevOps Carioca] Testes Automatizados
[DevOps Carioca] Testes Automatizados[DevOps Carioca] Testes Automatizados
[DevOps Carioca] Testes AutomatizadosSamanta Cicilia
 
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...Isaac de Souza
 
Não deixe para testar depois o que você pode testar antes.
Não deixe para testar depois o que você pode testar antes. Não deixe para testar depois o que você pode testar antes.
Não deixe para testar depois o que você pode testar antes. Tchelinux
 
Introdução a Testes Automatizados
Introdução a Testes AutomatizadosIntrodução a Testes Automatizados
Introdução a Testes Automatizadoselliando dias
 
Qualidade em Testes de Software
Qualidade em Testes de SoftwareQualidade em Testes de Software
Qualidade em Testes de SoftwareGDGFoz
 

Similar to Testing Sucks - Why and How to Test JS Code (20)

Test é para os fracos
Test é para os fracosTest é para os fracos
Test é para os fracos
 
Samanta Cicilia - MTC - Importância de Testes Automatizados para Continuous D...
Samanta Cicilia - MTC - Importância de Testes Automatizados para Continuous D...Samanta Cicilia - MTC - Importância de Testes Automatizados para Continuous D...
Samanta Cicilia - MTC - Importância de Testes Automatizados para Continuous D...
 
Importância de Testes Automatizados para Continuous Delivery & DevOps
Importância de Testes Automatizados para Continuous Delivery & DevOpsImportância de Testes Automatizados para Continuous Delivery & DevOps
Importância de Testes Automatizados para Continuous Delivery & DevOps
 
Ctai Teste De Software Aula 1
Ctai Teste De Software Aula 1Ctai Teste De Software Aula 1
Ctai Teste De Software Aula 1
 
PHPUnit e teste de software
PHPUnit e teste de softwarePHPUnit e teste de software
PHPUnit e teste de software
 
O que é Teste de Software?
O que é Teste de Software?O que é Teste de Software?
O que é Teste de Software?
 
Introdução ao Teste de Software - Uma abordagem prática
Introdução ao Teste de Software - Uma abordagem práticaIntrodução ao Teste de Software - Uma abordagem prática
Introdução ao Teste de Software - Uma abordagem prática
 
Paletra sobre TDD, ocorrida no #DevDojo
Paletra sobre TDD, ocorrida no #DevDojoPaletra sobre TDD, ocorrida no #DevDojo
Paletra sobre TDD, ocorrida no #DevDojo
 
TDC 2014 POA - Clean Code para Testers
TDC 2014 POA - Clean Code para TestersTDC 2014 POA - Clean Code para Testers
TDC 2014 POA - Clean Code para Testers
 
Palestra TDD Javou! #08 2016
Palestra TDD Javou! #08 2016Palestra TDD Javou! #08 2016
Palestra TDD Javou! #08 2016
 
[DevOps Carioca] Testes Automatizados
[DevOps Carioca] Testes Automatizados[DevOps Carioca] Testes Automatizados
[DevOps Carioca] Testes Automatizados
 
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
O que seus testes garantem, o funcionamento do código ou das funcionalidades ...
 
Be React. Do Tests!
Be React. Do Tests!Be React. Do Tests!
Be React. Do Tests!
 
TDC 2011 Trilha de Teste
TDC 2011 Trilha de TesteTDC 2011 Trilha de Teste
TDC 2011 Trilha de Teste
 
Precisa testar? - Parte 1
Precisa testar? - Parte 1Precisa testar? - Parte 1
Precisa testar? - Parte 1
 
Não deixe para testar depois o que você pode testar antes.
Não deixe para testar depois o que você pode testar antes. Não deixe para testar depois o que você pode testar antes.
Não deixe para testar depois o que você pode testar antes.
 
Testes de Sofware
Testes de SofwareTestes de Sofware
Testes de Sofware
 
Introdução a Testes Automatizados
Introdução a Testes AutomatizadosIntrodução a Testes Automatizados
Introdução a Testes Automatizados
 
Palestra Ufpb
Palestra UfpbPalestra Ufpb
Palestra Ufpb
 
Qualidade em Testes de Software
Qualidade em Testes de SoftwareQualidade em Testes de Software
Qualidade em Testes de Software
 

More from Leonardo Balter

Guia de Sobrevivência JS no mundo Open Source
Guia de Sobrevivência JS no mundo Open SourceGuia de Sobrevivência JS no mundo Open Source
Guia de Sobrevivência JS no mundo Open SourceLeonardo Balter
 
Potencial de Vendas do e-Commerce no Frontend - WOB2012
Potencial de Vendas do e-Commerce no Frontend - WOB2012Potencial de Vendas do e-Commerce no Frontend - WOB2012
Potencial de Vendas do e-Commerce no Frontend - WOB2012Leonardo Balter
 
Novo Cinto de Utilidades do Desenvolvedor JavaScript, WebAPIs e Open Web
Novo Cinto de Utilidades do Desenvolvedor JavaScript, WebAPIs e Open WebNovo Cinto de Utilidades do Desenvolvedor JavaScript, WebAPIs e Open Web
Novo Cinto de Utilidades do Desenvolvedor JavaScript, WebAPIs e Open WebLeonardo Balter
 
Receita do Sucesso no Mercado Front End
Receita do Sucesso no Mercado Front EndReceita do Sucesso no Mercado Front End
Receita do Sucesso no Mercado Front EndLeonardo Balter
 
Realize mais com HTML 5 e CSS 3 - EDTED / RS
Realize mais com HTML 5 e CSS 3 - EDTED / RSRealize mais com HTML 5 e CSS 3 - EDTED / RS
Realize mais com HTML 5 e CSS 3 - EDTED / RSLeonardo Balter
 
EDTED BH - HTML 5 e CSS 3 - Julho de 2011
EDTED BH - HTML 5 e CSS 3 - Julho de 2011EDTED BH - HTML 5 e CSS 3 - Julho de 2011
EDTED BH - HTML 5 e CSS 3 - Julho de 2011Leonardo Balter
 
WTF Javascript - FrontInRio 2011
WTF Javascript - FrontInRio 2011WTF Javascript - FrontInRio 2011
WTF Javascript - FrontInRio 2011Leonardo Balter
 
EDTED SP - HTML 5 e CSS 3 - Junho de 2011
EDTED SP - HTML 5 e CSS 3 - Junho de 2011EDTED SP - HTML 5 e CSS 3 - Junho de 2011
EDTED SP - HTML 5 e CSS 3 - Junho de 2011Leonardo Balter
 
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJ
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJRealize mais com HTML 5 e CSS 3 - 16 EDTED - RJ
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJLeonardo Balter
 
HTML 5 - Semana da Computação - UFF
HTML 5 - Semana da Computação - UFFHTML 5 - Semana da Computação - UFF
HTML 5 - Semana da Computação - UFFLeonardo Balter
 

More from Leonardo Balter (15)

Unit testing
Unit testingUnit testing
Unit testing
 
Insustentavel js
Insustentavel jsInsustentavel js
Insustentavel js
 
GruntJS + Wordpress
GruntJS + WordpressGruntJS + Wordpress
GruntJS + Wordpress
 
Guia de Sobrevivência JS no mundo Open Source
Guia de Sobrevivência JS no mundo Open SourceGuia de Sobrevivência JS no mundo Open Source
Guia de Sobrevivência JS no mundo Open Source
 
Potencial de Vendas do e-Commerce no Frontend - WOB2012
Potencial de Vendas do e-Commerce no Frontend - WOB2012Potencial de Vendas do e-Commerce no Frontend - WOB2012
Potencial de Vendas do e-Commerce no Frontend - WOB2012
 
Novo Cinto de Utilidades do Desenvolvedor JavaScript, WebAPIs e Open Web
Novo Cinto de Utilidades do Desenvolvedor JavaScript, WebAPIs e Open WebNovo Cinto de Utilidades do Desenvolvedor JavaScript, WebAPIs e Open Web
Novo Cinto de Utilidades do Desenvolvedor JavaScript, WebAPIs e Open Web
 
Extreme Web Performance
Extreme Web PerformanceExtreme Web Performance
Extreme Web Performance
 
temp EWP
temp EWPtemp EWP
temp EWP
 
Receita do Sucesso no Mercado Front End
Receita do Sucesso no Mercado Front EndReceita do Sucesso no Mercado Front End
Receita do Sucesso no Mercado Front End
 
Realize mais com HTML 5 e CSS 3 - EDTED / RS
Realize mais com HTML 5 e CSS 3 - EDTED / RSRealize mais com HTML 5 e CSS 3 - EDTED / RS
Realize mais com HTML 5 e CSS 3 - EDTED / RS
 
EDTED BH - HTML 5 e CSS 3 - Julho de 2011
EDTED BH - HTML 5 e CSS 3 - Julho de 2011EDTED BH - HTML 5 e CSS 3 - Julho de 2011
EDTED BH - HTML 5 e CSS 3 - Julho de 2011
 
WTF Javascript - FrontInRio 2011
WTF Javascript - FrontInRio 2011WTF Javascript - FrontInRio 2011
WTF Javascript - FrontInRio 2011
 
EDTED SP - HTML 5 e CSS 3 - Junho de 2011
EDTED SP - HTML 5 e CSS 3 - Junho de 2011EDTED SP - HTML 5 e CSS 3 - Junho de 2011
EDTED SP - HTML 5 e CSS 3 - Junho de 2011
 
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJ
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJRealize mais com HTML 5 e CSS 3 - 16 EDTED - RJ
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJ
 
HTML 5 - Semana da Computação - UFF
HTML 5 - Semana da Computação - UFFHTML 5 - Semana da Computação - UFF
HTML 5 - Semana da Computação - UFF
 

Testing Sucks - Why and How to Test JS Code

  • 1. Testing Sucks Leo Balter - BrazilJS 2012 JS
  • 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
  • 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”
  • 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”.
  • 13. A Síndrome do “o que está funcionando não se 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
  • 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 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. 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
  • 24. Esse código funciona! • Um código pode funcionar perfeitamente • Estar 100% testado • e não cumprir 10% do seu papel
  • 25. Fluxo
  • 27. Especificação Plano de Testes Fluxo
  • 28. Especificação Plano de Testes Fluxo Testes
  • 31. Validação Plano de Testes Especificação
  • 32. Validação Plano de Testes Testes Especificação
  • 33. Validação Plano 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!
  • 47. Tudo é testável • Complexidade vs Criticidade • window.location.replace()
  • 49. Testes Unitários Interface Funcionais Desempenho Integração
  • 51. Firefox Chrome Opera IE 8, 9[, 10, ...]
  • 52. Firefox Chrome Mobile Opera IE 8, 9[, 10, ...]
  • 53. PhantomJS Webkit
  • 54. Ferramentas QUnit NodeUnit Mocha Vows Jasmine
  • 55. Estilos de Testes TDD BDD Exports
  • 56. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  • 57. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  • 58. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  • 59. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  • 60. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  • 61. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  • 62. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  • 63. TDD module( "Basics" ); test( "hello test", function() {   ok( 1 == "1", "Passed!" ); }); http://qunitjs.com/
  • 64. TDD module( "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.
  • 75. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  • 76. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  • 77. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  • 78. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  • 79. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  • 80. BDD describe("A suite", function() { it("spec with an expectation", function(){ expect(true).toBe(true); }); });
  • 81. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  • 82. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  • 83. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  • 84. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  • 85. Exports module.exports = { test1: function (test) { test.equals(this.foo, 'bar'); test.done(); } };
  • 87. HTML Estático JavaScript Testes
  • 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. <!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>
  • 90. 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
  • 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. 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
  • 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. 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(); });
  • 112.
  • 114. 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!' ); }
  • 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. test( 'stubbed carly()', 1, function() { var stub = Dexter.stub( window, 'carly', function() { return 'relax'; }); equal( meSad( true ), 'relax', 'stubbed carly!' ); stub.restore(); });
  • 121. test( 'stubbed carly()', 1, function() { var stub = Dexter.stub( window, 'carly', function() { return 'relax'; }); equal( meSad( true ), 'relax', 'stubbed carly!' ); stub.restore(); });
  • 122.
  • 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. 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 }); });
  • 133. 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 }); });
  • 134. 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 }); });
  • 135. Começar a criar testes?
  • 137. Referências • Coding Dojo • Inicialize um projeto com o GruntJS • TDD - Kent Back • Engenharia de Software - Roger S Pressman • Testable JavaScript - Mark Ethan Trostler *
  • 138.
  • 139. Obrigado! @leobalter leo@balter.com.br JS http://search.cpan.org/~leobalter/ • @garu_rj • @blabos • @aoqfonseca