Code Coverage em Javascript

Istanbul

Já conversamos um pouco sobre TDD/BDD e montamos nosso ambiente para começar a brincar com testes. Que tal agora verificarmos como anda nossa cobertura de código? Let’s go!

Code Coverage

Ferramentas de Code Coverage testam quantos porcento do nosso código está coberto por testes. Se você acompanhou o post anterior sobre testes, você já deve ter o Istanbul instalado. Se não tiver, dá uma lida lá no post e prepare seu ambiente :D

Começando

Para facilitar, vamos começar usando o mesmo módulo do post anterior, o sum.js, e ver quanto o nosso módulo está coberto por testes. Na raiz do seu projeto, execute o comando:

1
istanbul cover _mocha tests/sumTest.js

Que vai executar o Istanbul, fazendo coverage, e dizendo a ele que estamos usando a interface do Mocha para escrever nossos testes.

E esse será o resultado gerado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ istanbul cover _mocha tests/sumTest.js


sum.js
✓ sum of 2 + 3 should return 5
✓ sum of 10 + 10 should return 20


2 passing (11ms)

=============================================================================
Writing coverage object [/var/www/tdd/coverage/coverage.json]
Writing coverage reports at [/var/www/tdd/coverage]
=============================================================================

=============================== Coverage summary ===============================
Statements : 100% ( 2/2 )
Branches : 100% ( 0/0 )
Functions : 100% ( 1/1 )
Lines : 100% ( 2/2 )
================================================================================

Nesse resultado, no terminal, ele mostra o resumo de tudo o que os nossos testem cobrem do nosso módulo. Perceba que ele criou um diretório coverage/ dentro do nosso projeto. Se você acessar via browser a URL do seu projeto + /coverage/lcov-report/, vai conseguir navegar pelos arquivos e visualizar quais partes estão ou não cobertas por testes.

Coverage do arquivo sum.js

Nesse nosso exemplo, todo o nosso código está coberto por testes! Se continuarmos escrevendo TDD corretamente, escrevendo sempre um teste que quebre, um baby step para passar, e fazendo o refactor, nós iremos escrever sempre o mínimo possível de código, e todo ele estará coberto pelos testes.

IMPORTANTE:
É importante salientar que um código com 100% de cobertura não garante que todas as possibilidades foram testadas, mas que, tudo o que está sendo testado está passando por todo o código. Mas, como vimos no módulo sum.js, ainda podemos fazer mais uns testes em áreas que já estão cobertas por outros testes.

Só por questões de visualização, vamos adicionar um pouco mais de código no nosso módulo para ver a cobertura cair (NÃO FAÇA ISSO EM CASA!). No arquivo sum.js:

1
2
3
4
5
6
module.exports = function sum( number1, number2 ) {
if( isNaN( number1 ) || isNaN( number2 ) ) {
return;
}
return number1 + number2;
};

E execute novamente o comando para verificarmos a cobertura:

1
istanbul cover _mocha tests/sumTest.js

Olhando no navegador, podemos ver que a cobertura já diminuiu:

Coverage diminuiu

O I quer dizer que aquele IF não está coberto. Se fosse um E, faltava cobertura para o ELSE. E a linha vermelha é o Statement que não está coberto pelos testes.

Para cobrir essa parte do nosso código por testes, nós precisamos fazer a seguinte pergunta a nós mesmos:

- Essa parte não coberta por testes: eu realmente preciso dela no meu código?

Se a sua resposta for SIM, então você precisa escrever um teste para cobrí-la. Senão, remova do seu código. Simples assim.

No nosso caso, vamos precisar, pois precisamos saber se o a nossa função realmente recebeu um número. Senão, iremos retornar undefined. Vamos então fazer nosso teste. No arquivo tests/sumTest.js, adicione mais um teste:

1
2
3
it( 'If any parameter is not number, should return undefined', function() {
should( sum( 1, 'arroz' ) ).not.be.ok;
});

Perae, porque você mudou o formato do uso do ShouldJS?

Você está retornando undefined quando passar um valor que não seja número por parâmetro na função sum(), certo? Sabemos que undefined e null não têm propriedades. Logo, sempre que você precisar testar se um valor é undefined ou null, você precisa usar o should como função, ok? ;)

Voltando: se o usuário passar um parâmetro que não seja número, devemos retornar undefined. Na nossa asserção, o not.be.ok quer dizer exatamente isso: algo que não esteja _ok_, ou que seja diferente de true. Em JS, os valores para isso são: '', null, undefined, 0, NaN. Para ver todas as asserções do ShouldJS, acesse esse link.

Vamos agora executar o Istanbul e ver como o nosso teste se comporta e o quanto ele cobre do nosso código:

1
istanbul cover _mocha tests/sumTest.js

E pronto! Agora nosso código está com 100% de cobertura novamente :D

Novamente 100% coberto

Extras

Para facilitar a execução dos testes, podemos usar o próprio NPM, fazendo algumas malandragens.

Primeiro crie um package.json com o comando npm init. Confirme os dados e edite o arquivo.

Na diretiva scripts, adicione:

1
2
3
4
"scripts": {
"test": "mocha -w tests/**/*.js",
"coverage": "istanbul cover _mocha tests/**/*.js"
},

Então você pode executar os seus testes com o comando npm test. O -w ali significa que o Mocha irá assistir a cada alteração que fizermos no nosso arquivo de teste, e já executará o teste automaticamente.

Para fazer o Coverage, execute npm run coverage, e pronto!

Espero que tenha ficado claro! Dúvidas, poste nos comentários :)

Ah, e não esqueça de se inscrever no RSS :D

Sobre o #1postperday: https://blog.da2k.com.br/2014/12/31/um-post-por-dia/

Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: https://github.com/fdaciuk/fdaciuk.github.io/issues/1