Testes de mutação podem dar ótimos indicadores de como / se os seus testes estão realmente preservando o estado de comportamento original da sua regra de negócio. Neste breve texto irei introduzir conceitualmente o que são testes de mutação e apresentar uma ferramenta para fazer esse tipo de análise.
A ideia é bem simples: mutações são alterações no seu código, e se essas alterações no seu código não reprovarem no seu teste, pode ser que o seu teste seja ruim ou incompleto. Um exemplo rápido, imagine uma função que verifica se alguém é maior de 18 anos:
public class Verificador
{
public bool EhMaiorDeIdade(int idade)
{
return idade >= 18;
}
}
E que para o teste dessa função você tenha um único teste:
[Fact]
public void Deve_Retornar_Verdadeiro_Para_Uma_Idade_Maior_Ou_Igual_18()
{
var verificador = new Verificador();
var resultado = verificador.EhMaiorDeIdade(19);
Assert.True(resultado);
}
No primeiro olhar, tudo parece ok, a função é para verificar se é maior de idade, 19 anos seria alguém maior de idade o teste passou, então está tudo certo, certo?! É claro que esse é um exemplo simples e fácil de verificar que não, mas uma modificação (mutação) de "return idade >= 18;" para "return idade > 18;" continuaria fazendo com que o seu teste fosse aprovado, porém essa modificação quebrou a sua regra de negócio mas seu teste - que deveria ser aquilo que te alerta que alterações recentes alteraram crucialmente o comportamento inicialmente definido pela sua regra de negócio - não te diz nada.
Aqui entra o Stryker, uma ferramenta que irá fazer essas mutações no seu código, e para cada mutação que for possível fazer, ela irá executar o teste. Se o seu teste passar com uma mutação (alteração), seu teste está incompleto; Se as mutações fizerem o seu teste reprovar elas, você está no caminho correto; digo "no caminho correto" porque as mutações feitas pela ferramenta tem sua limitações e que mutações/alterações feitas ao decorrer do tempo por programadores reais, têm bem mais sutilezas.
Eu criei aqui dois projetos bem simples, um projeto console e outro é um projeto de testes. Caso queira fazer o mesmo:
dotnet new console -n console.mutation; dotnet new sln -n solucao; dotnet new xunit -n teste.mutation
A ferramenta você pode instalar com:
dotnet tool install -g dotnet-stryker
Entre no diretório do projeto de teste e rode:
dotnet-stryker
No caso do nosso exemplo, teríamos o seguinte resultado pelo terminal:
100.00% │ Testing mutant 2 / 2 │ K 1 │ S 1 │ T 0 │ ~0m 00s │ 00:00:02
Killed: 1
Survived: 1
Timeout: 0
Mas também tem uma página html disponibilizada para ver com mais detalhes:
O diff em verde no código é a mutação feita pela ferramenta, e como indica no filtro ela foi a mutação que sobreviveu. Como Podemos matar ela? Simples, testando melhor: Se a função verifica se um número é maior ou igual 18, é fácil de ver que nosso teste testa apenas se maior e não se é maior ou igual. Ao teste vamos adicionar:
[Fact]
public void Deve_Retornar_Verdadeiro_Para_Uma_Idade_Igual_18()
{
var verificador = new Verificador();
var resultado = verificador.EhMaiorDeIdade(18);
Assert.True(resultado);
}
O teste completo fica assim:
public class TesteVerificador
{
[Fact]
public void Deve_Retornar_Verdadeiro_Para_Uma_Idade_Maior_Ou_Igual_18()
{
var verificador = new Verificador();
var resultado = verificador.EhMaiorDeIdade(19);
Assert.True(resultado);
}
[Fact]
public void Deve_Retornar_Verdadeiro_Para_Uma_Idade_Igual_18()
{
var verificador = new Verificador();
var resultado = verificador.EhMaiorDeIdade(18);
Assert.True(resultado);
}
}
E rodando novamente a ferramenta temos:
100.00% │ Testing mutant 2 / 2 │ K 2 │ S 0 │ T 0 │ ~0m 00s │ 00:00:02
Killed: 2
Survived: 0
Timeout: 0
E na parte gráfica:
Conseguimos matar a mutação e assim produzindo um teste mais significante.
Espero que tenha gostado do texto e que tenha aprendido algo novo. Qualquer dúvida, leia a documentação. Até o próximo texto.
Top comments (0)