Glossário · Fundamentos de testes
Cobertura de código
Em inglês: Code coverage
Também chamado de: cobertura de linhas, cobertura de branches, cobertura de decisão, cobertura de instruções
Definição
O percentual do código-fonte (linhas, instruções, branches ou funções) executado durante os testes. Mostra o que não foi testado, não o que foi bem testado.
A cobertura de código mede quanto do código foi executado por uma rodada de testes. Uma ferramenta instrumenta o código (JaCoCo para Java, Istanbul/nyc ou a cobertura do V8 para JavaScript, coverage.py para Python), executa os testes e informa quais linhas e branches foram atingidos. É uma métrica de caixa-branca e costuma ser coletada para testes unitários e de integração.
Tipos de cobertura
Considere:
int shippingCost(double total, boolean isMember) {
if (total >= 100 || isMember) {
return 0;
}
return 5;
}
- Cobertura de instruções (linhas): os dois
returnforam executados? Dois testes,(150, false)e(20, false), dão 100%. - Cobertura de branches (decisão): o
iffoi verdadeiro e falso? Os mesmos dois testes também dão 100%. - Cobertura de condições: cada subcondição booleana foi avaliada como verdadeira e como falsa? Os testes acima nunca tornaram
isMemberverdadeiro, então ela não está completa. Acrescentar(20, true)resolve isso. - Cobertura de funções: cada função foi chamada pelo menos uma vez?
A cobertura de branches geralmente é uma meta mais útil do que a de linhas, porque uma única linha pode esconder vários caminhos.
O que a cobertura não diz
A cobertura prova que o código rodou, não que ele foi verificado. Este teste dá 100% de cobertura de linhas e de branches do método acima e não verifica nada:
@Test
void runsShippingCost() {
shippingCost(150, false);
shippingCost(20, false);
}
A cobertura também não revela código que falta. Se o requisito diz que membros de uma certa região pagam frete e ninguém implementou isso, não há linhas para ficarem descobertas. O teste de mutação é a forma usual de medir se os testes realmente detectam falhas.
Como usar bem
- Olhe as linhas não cobertas, não só o número. Um tratamento de erro não testado no fluxo de pagamento importa mais do que um
toString()não testado. - Use como gate a cobertura do código alterado, por exemplo “código novo precisa ter pelo menos 80% de cobertura de branches”, em vez de um percentual global que leva as pessoas a testar getters triviais.
- Nunca trate 100% como objetivo. Quando uma métrica vira meta, aparecem testes sem asserções.