Teste de mutação em .Net
Você já se perguntou se os testes que você escreve são de fato eficientes?
Temos como conhecimento base que o código de nossa aplicação está “seguro” quando criamos testes que garantam a qualidade e previnam regressões.
Mas quem garante a qualidade dos testes?
Quem testa os testes?
Essa é uma pergunta bem comum no cenário de qualidade, quando falamos de testes em aplicações.
É bem comum olharmos para a cobertura de código para mensurar a eficiência dos testes que criamos. Porém quantidade não significa qualidade!
Mutantes em ação!
Os testes de mutação surgem nesse cenario provocando alterações, no seu código, com a finalidade de quebrar o teste que cobre o trecho em questão.
Se pelo menos uma (aqui é um pouco mais abrangente, falaremos melhor mais abaixo) dessas mutações causar a quebra do teste, ou seja fazer o teste falhar, consideramos que o código está de fato coberto.
Talk is cheap… Show me the code
Se o conceito de testes mutantes ainda não ficou muito claro, acredito que com o demo a seguir algumas dúvidas devem ser respondidas.
No exemplo a seguir, eu criei um projeto Xamarin.Forms, com uma ViewModel que possui uma lógica de validação de máscara de CPF.
À partir da versão 1.2.0 o Stryker suporta projetos Xamarin.Forms para testes mutantes. 🎉🎉
Em cima dessa lógica eu criei os testes de unidade abaixo:
Após isso fiz algumas configurações para os testes mutantes através de um arquivo stryker-config.json
Aqui eu basicamente configurei o nível das mutações pro mais avançado disponível pela ferramenta, quais relatórios eu quero gerar e os “limites” de percentuais para considerar um código de fato coberto.
Entenda:
- O
High
significa o mínimo de pontuação a se alcançar para um código ser considerado “bom” na cobertura dos testes (Aqui eu defini como 80%). - O
Low
significa o mínimo aceitavel para considerar que um código está coberto. - O
Break
define a pontuação para o stryker retornar um código de erro, então podemos utilizar para quebrar uma pipeline por exemplo, caso a pontuação do teste mutante seja tão baixa.
Depois de ter instalado a ferramenta stryker, eu rodei ela no diretório onde fica o projeto de testes.
Com isso obtivemos o resultado de 10 mutantes “mortos”, ou seja, que quebraram meus testes de unidade ao alterar a lógica da minha ViewModel.
É uma boa pontuação! De 12 mutantes 10 foram mortos nessa execução.
No relatório HTML podemos ver com mais detalhes qual foi a atuação do Striker no nosso código:
Aqui no dashboard podemos ver que foram criados 13 mutantes ao total, para a MyViewModel
, mas um deles não estava coberto (provavelmente uma das condições if/else).
Atingimos então o score de 76.92, assim ficamos na marca do Low que definimos no nosso arquivo de configuração.
Se clicarmos no nome do arquivo, temos mais detalhes sobre a mutação que aconteceu naquele código:
Aqui podemos ver que foram aplicadas algumas mutações em cima do meu regex e muitas delas quebraram meus testes.
Por fim, temos aqui a condição onde foi criado uma mutação mas os nossos testes não cobrem, pois em nenhum teste eu envio um input nulo/vazio.
E ai? Curtiu a ferramenta?
O Striker também possuí uma extensão para adicionar o dashboard, do relatório HML, em uma aba no AzureDevops. Confere lá na doc como configurar.
Você encontra o exemplo desse artigo no meu github: