DEV Community

Cover image for Testes de Mutação - Garanta já a qualidade do seu código
Gabriel Augusto Morato dos Santos
Gabriel Augusto Morato dos Santos

Posted on Edited on

Testes de Mutação - Garanta já a qualidade do seu código

Hello World, sejam bem vindos ao meu artigo relacionado à testes de mutação.

Agradecimentos especiais:

Antes de iniciarmos, gostaria muito de agradecer ao meu amigo de trabalho Paulo Ricardo pelo incentivo de estar escrevendo esse artigo e poder compartilhar a minha visão dessa ferramenta com o restante de vocês.

Afinal, o que é o Teste de Mutação?

image

O Pitest faz uma mutação no seu projeto, ele permite que você garanta uma margem de cobertura real dentro dos seus testes fazendo uma “cópia” do projeto e inserindo erros para ver se o seus testes irão falhar após a mutação. Quando o teste falha o mutante é morto. Caso algum mutante sobreviva isso significa que você precisa fazer mais testes unitários, os mutantes vivos servem de input para criar mais testes.

Ok, mas como isso me ajuda com a qualidade do meu código?

image

Devido as clássicas correrias que os desenvolvedores precisam entrar para entregar um determinado projeto, acaba que o teste é feito mais para poder aumentar a cobertura do código, só que isso não é o correto, os testes vem com o objetivo de fornecer mais a qualidade do que você está entregando para algum cliente ou consumidor e também documentar para que outro desenvolvedor entenda melhor o seu código, mais pra frente vocês irão entender em que ponto quero chegar :)

Quais tecnologias iremos utilizar?

image

Para esse artigo em questão, iremos precisar ter as seguintes tecnologias no nosso projeto:

  1. Java 8+: Linguagem de Programação Java na versão 8+
  2. Junit 5: Framework para desenvolvimento de testes
  3. Maven: Ferramenta de automação para compilação
  4. Pitest: Ferramenta para realizar os testes mutantes
  5. Spring: Framework de programação

Não irei entrar muito a dentro de todas as tecnologias utilizadas pois não é o nosso objetivo desse artigo.

Configurando o nosso projeto:

image

Para que possamos utilizaf o pitest, precisamos fazer o uso do Junit 4 ou superior, mas como foi dito anteriormente, iremos utilizar o Junit5:



<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <version>1.7.1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.7.1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.7.1</version>
    <scope>test</scope>
</dependency>


Enter fullscreen mode Exit fullscreen mode

Também será necessário que a gente adicione no nosso projeto o plugin do pitest que é o objetivo principal do nosso artigo:



            <plugin>
                <groupId>org.pitest</groupId>
                <artifactId>pitest-maven</artifactId>
                <version>1.4.11</version>
                <dependencies>
                    <dependency>
                        <groupId>org.pitest</groupId>
                        <artifactId>pitest-junit5-plugin</artifactId>
                        <version>0.8</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <targetClasses>
                        <param>SeuPacoteDeClasse.*</param>
                    </targetClasses>
                    <targetTests>
                        <param>SeuPacoteDeTeste.*</param>
                    </targetTests>
                </configuration>
            </plugin>


Enter fullscreen mode Exit fullscreen mode

Observação: Existem outras configurações que você pode inserir no plugin conforme a sua preferência, como por exemplo, excluir uma determinada classe ou pacote que não irá ser testado:



<excludedClasses>
 <param>PacoteDasSuasClasses.*</param>
 <param>PacoteDasSuasClasses.SouUmaClasse</param>
</excludedClasses>


Enter fullscreen mode Exit fullscreen mode

Só espero que você não exclua o projeto inteiro, ok? :D

Revelando a falha de fazer teste apenas para cobertura:

image

Conforme foi dito anteriormente, devido à alguma correria ou até mesmo por falta de conhecimento, o desenvolvedor costuma fazer o teste apenas pela cobertura ou acaba esquecendo de inserir alguma validação importante, então vamos analisar o seguinte cenário:

  • Dentro do nosso projeto temos uma classe chamada UsuarioTranslator

  • No nosso método receberemos como parâmetros uma String(nome) e um Integer(idade)

  • Após isso iremos fazer a instância da classe Usuario e iremos settar os parâmetros recebidos em seus respectivos atributos

  • Logo em seguida, iremos retornar o usuario



public final class UsuarioTranslator {

    private UsuarioTranslator() {}

    public static Usuario of(final String nome, final Integer idade) {
        final Usuario usuario = new Usuario();

        usuario.setNome(nome);
        usuario.setIdade(idade);

        return usuario;
    }
}


Enter fullscreen mode Exit fullscreen mode

Ok, após entendermos o objetivo do nosso método, vamos para a nossa classe de teste, UsuarioTranslatorTest:



class UsuarioTranslatorTest {

    @Test
    @DisplayName("Deverá retornar Usuario - Quando sucesso")
    void of_Usuario_QuandoSucesso() {
        final Integer idade = 10;
        final String nome = "Dudu";

        final Usuario usuario = UsuarioTranslator.of(nome, idade);

        Assertions.assertNotNull(usuario);
        Assertions.assertEquals(nome, usuario.getNome());
    }
}


Enter fullscreen mode Exit fullscreen mode

Como podemos ver, fizemos a chamada do método da nossa classe e fizemos as seguintes verificações:

  • Verificamos que o objeto de retorno não está nulo
  • Verificamos que nome* esperado é igual ao nome informado no usuario

Vamos conferir a nossa cobertura?

Captura de tela de 2021-03-16 23-31-44

Mas afinal, nesse exemplo simples não tivemos nenhum problema, onde estava o nosso erro?

Exatamente, esquecemos de fazer a validação se o atributo de idade foi settado corretamente, vamos ver o que o Pitest tem a dizer?

Entrando mais na ferramenta:

image

Para que possamos executar o Pitest basta executar o seguinte comando no terminal do seu projeto:



mvn org.pitest:pitest-maven:mutationCoverage



Enter fullscreen mode Exit fullscreen mode

Ou executar o plugin diretamente na sua IDE clicando na opção pitest:mutationCoverage, a escolha é sua :)

Captura de tela de 2021-03-16 23-41-57

Após fazer a execução e tiver configurado direitinho o seu projeto até aqui, você irá ter o seguinte resultado:

Captura de tela de 2021-03-16 23-51-46

Como podemos ver acima, o Pitest fez a geração de 5 mutações e com o nosso teste conseguimos matar apenas 3, mas não se preocupe, para que você tenha uma visão mais analítica, o Pitest gera pra você um relatório, para que possamos acessar o mesmo basta seguir o seguinte caminho:

  • target
  • pit-reports
  • index.html

Captura de tela de 2021-03-16 23-54-32

Como podemos ver, o Pitest tirou a nossa linha do usuario.setIdade(idade); e disse que se removermos a chamada dessa linha, o resultado será o mesmo e sabemos que isso não é verdade, correto? :)

Então agora basta voltarmos na nossa classe de teste e fazer as suas devidas alterações.

Obrigado pessoal:

image

Agradeço a todos vocês por terem lido o meu artigo, como foi dito esse foi o primeiro de muitos que virão, então caso tenham gostado ou tenha um comentário para que possa estar me apoiando e me incentivando ficarei extremamente grato :)

Agora deixo um desafio especial para que você execute o Pitest no seu projeto e diga qual foi a sua reação quando viu o resultado :D

Observação: Na minha primeira vez não foi muito positivo, mas me ajudou a ter uma qualidade maior nos projetos :D

Top comments (8)

Collapse
 
pedrogabrielsantoslima profile image
pedrogabrielsantoslima •

Cara excelente esse artigo, tudo explicado passo-a-passo, com certeza vai ajudar bastante. Parabéns!!!

Collapse
 
gabrielaugusto1996 profile image
Gabriel Augusto Morato dos Santos • • Edited

Muito obrigado Pedro, fico feliz que você tenha gostado :)

Collapse
 
mateusflip profile image
Mateus Ramos •

Nunca tinha ouvido falar do Pitest, muito obrigado! Curti demais.
Já quero acompanhar suas próximas postagens

Collapse
 
gabrielaugusto1996 profile image
Gabriel Augusto Morato dos Santos •

Muito obrigado pelo seu feedback Mateus, fico muito feliz de saber que eu estou ajudando mais um amigo dev =)

Collapse
 
danillonc profile image
Danillo Coradello •

Bacana o propósito da lib.

Collapse
 
gabrielaugusto1996 profile image
Gabriel Augusto Morato dos Santos •

Também acho super massa Danilão :)

Collapse
 
ggmoura profile image
Gleidson Guimarães Moura •

Parabéns Gabriel, assunto extremamente relevante, e muito bem abordado.

Collapse
 
gabrielaugusto1996 profile image
Gabriel Augusto Morato dos Santos •

Muito obrigado Gleidson, obrigado pelo seu feedback :)