O Que É Teste de Mutação?
O teste de mutação mede a qualidade dos seus testes introduzindo deliberadamente pequenos bugs e verificando se os testes os detectam.
A cobertura informa qual código foi executado durante os testes, mas não se os testes perceberiam um bug. O teste de mutação responde a essa pergunta mais difícil. Ele muta seu código, invertendo um operador ou alterando uma constante, e roda a suíte novamente. Se um teste falha, o mutante é "morto"; se todos os testes ainda passam, o mutante "sobreviveu", expondo um ponto fraco.
Como os mutantes são criados
Uma ferramenta de mutação gera muitas versões levemente alteradas do seu código, cada uma com uma pequena mudança: um mais vira um menos, um menor-que vira um menor-ou-igual-a, um valor de retorno é removido. Cada mutante representa um bug realista que um desenvolvedor poderia introduzir.
Morto versus sobrevivente
Para cada mutante a suíte roda novamente. Se pelo menos um teste falha, seus testes detectaram o bug e o mutante é morto. Se todos os testes ainda passam, o mutante sobreviveu, ou seja, seus testes não teriam detectado aquele bug. Os sobreviventes apontam precisamente para asserções fracas ou ausentes.
O escore de mutação
O escore de mutação é a porcentagem de mutantes mortos. Diferente da cobertura, ele reflete a qualidade das asserções, não apenas a execução. Um escore de mutação alto é forte evidência de que seus testes realmente verificam o comportamento, e é por isso que é uma métrica mais exigente.
Um exemplo rápido
Se uma ferramenta muda um > para um >= e nenhum teste falha, o caso de fronteira não está testado, um sobrevivente que vale a pena corrigir.
if (age > 18) { ... } // original
if (age >= 18) { ... } // mutant: did any test catch it?Teste de mutação e custo no CI
O teste de mutação é caro: ele roda a suíte uma vez por mutante, então pode ser ordens de magnitude mais lento que uma execução normal de testes. As equipes costumam rodá-lo à noite ou em um cronograma em vez de a cada push, e o paralelizam intensamente. Distribuir os mutantes entre runners rápidos é o que o mantém viável.
Principais conclusões
- O teste de mutação avalia os testes verificando se eles detectam bugs injetados.
- Mutantes sobreviventes revelam asserções fracas ou ausentes.
- É custoso, então rode em um cronograma e paralelize entre os runners.