Pular para o conteúdo
SDETRole
SDETRole

Glossário · Fundamentos de testes

Teste de mutação

Em inglês: Mutation testing

Também chamado de: análise de mutação, mutation score, testes de mutação, score de mutação

Definição

Técnica que injeta pequenos bugs deliberados (mutantes) no código e roda os testes de novo para medir se a suíte realmente detecta falhas.

O teste de mutação (mutation testing) testa os seus testes. Uma ferramenta cria muitas cópias do código, cada uma com uma pequena alteração, como >= virando >, + virando - ou o corpo de um método substituído por return null. Cada cópia alterada é um mutante. A suíte de testes roda contra cada mutante. Se pelo menos um teste falha, o mutante é morto (killed). Se todos os testes continuam passando, o mutante sobreviveu (survived), o que significa que os testes não perceberiam aquele bug.

Mutation score (score de mutação) = mutantes mortos / total de mutantes (excluindo os mutantes equivalentes).

Exemplo

boolean isAdult(int age) {
    return age >= 18;
}

Testes: isAdult(30) é true, isAdult(10) é false. A cobertura de linhas e de branches é de 100%.

A ferramenta cria um mutante com age > 18. Os dois testes continuam passando, então o mutante sobrevive. Isso expõe um teste de valor-limite que está faltando: ninguém verificou isAdult(18). Adicioná-lo mata o mutante. A cobertura não conseguiria te mostrar isso; o teste de mutação consegue.

Ferramentas

  • Java: PIT (pitest), com plugins para Maven e Gradle e suporte a JUnit 5.
  • JavaScript/TypeScript: StrykerJS, que também tem versões para .NET e Scala.
  • Python: mutmut e Cosmic Ray.

Limites práticos

  • Custo. Cada mutante é uma execução de testes. As ferramentas reduzem isso rodando apenas os testes que cobrem a linha mutada e executando de forma incremental sobre o código alterado, mas ainda assim é muito mais lento que uma execução normal. A maioria dos times roda à noite ou sobre os arquivos alterados em um pull request, e não a cada commit para a base de código inteira.
  • Mutantes equivalentes. Algumas alterações não mudam o comportamento, por exemplo trocar i < n por i != n em um loop no qual i sempre cresce de um em um a partir de um valor abaixo de n. Nenhum teste consegue matá-los, então eles precisam ser revisados e excluídos manualmente.
  • Funciona melhor no nível de unidade. O teste de mutação foi pensado para testes unitários rápidos e determinísticos. Rodá-lo contra testes de UI lentos raramente é viável.

Use os mutantes sobreviventes como uma lista de tarefas de assertions que estão faltando, especialmente na lógica de negócio, em vez de perseguir um score perfeito.

Digite para buscar em todo o SDETRole.

Busca de texto completo com Pagefind · roda no seu navegador Abrir página de busca →