DEV Community

Marlo Henrique
Marlo Henrique

Posted on • Edited on

2

Configurando testes de mutação utilizando Stackspot EDP

A Stackspot EDP tem se mostrado um forte aliado no processo de automação de testes, permitindo a criação de novos projetos e a complementação de projetos já existentes.

Neste artigo, vamos explorar como configurar testes de mutação em um projeto backend existente usando um plugin desenvolvido com a Stackspot EDP.

O que são testes de mutação?👥

O Teste de Mutação é uma técnica de teste de software que consiste em alterar partes específicas do código-fonte para verificar se os testes elaborados conseguem identificar os erros resultantes das mudanças.

O objetivo é avaliar a qualidade dos testes e sua capacidade de detectar falhas no código-fonte que foi modificado, por isso as mudanças ou também chamados de mutantes são pequenas para não afetar o objetivo geral do programa.

Essa técnica é também conhecida como estratégia de teste baseada em falhas e é principalmente usada para verificar a qualidade dos testes de unidade que foram desenvolvidos.

Etapas para execução📑

Image description

O processo de Teste de Mutação envolve alguns passos, entre eles:

  • Primeiro, falhas são introduzidas no código-fonte, criando mutantes que devem falhar na execução dos testes.
  • Em seguida, os casos de teste são aplicados tanto ao programa original quanto aos mutantes. Se os resultados dos programas original e mutante forem diferentes, o mutante é eliminado pelo caso de teste, demonstrando sua eficácia.
  • Se os resultados forem os mesmos, o mutante é mantido ativo, e teste mais eficazes precisam ser criados para detectar a mudança entre o programa original e o mutante.

O objetivo final é garantir a qualidade dos casos de teste e a robustez do software a mudanças.

Mudanças em um programa mutante📐

Existem diversas técnicas utilizadas para gerar mutantes, sendo as mais comuns:

  • Operadores de substituição de operando: substituem um operando por outro ou por um valor constante.
  • Operadores de modificação de expressão: alteram a expressão original, inserindo ou substituindo operadores.
  • Operadores de modificação de instrução: alteram a instrução original, inserindo ou removendo instruções.

Essas técnicas podem ser combinadas para gerar mutantes com diferentes tipos de falhas, aumentando a eficácia do Teste de Mutação.

Para obter mais informações sobre as diferentes abordagens de geração de mutantes, você pode consultar a documentação da ferramenta pitest, que está disponível no seguinte link.

Ferramentas🔨

Existem várias ferramentas disponíveis para realizar testes de mutação em projetos Java/Kotlin. Uma das ferramentas mais conhecidas é o Pitest, que será utilizada neste artigo.

Pré-requisito📑

Projeto de exemplo📚

Neste artigo, utilizaremos o projeto pequeno investidor, uma aplicação pessoal que disponibiliza informações do mercado financeiro por meio de uma API que extrai as informações utilizando web scraping.

O projeto foi criado utilizando a linguagem Java e utiliza o gerenciador de dependências Maven. A estrutura do projeto é a seguinte:

├───src
│   ├───main
│   │   ├───java
│   │   │   └───com
│   │   │       └───money
│   │   │           └───pequenoinvestidor
│   │   │               ├───configuration
│   │   │               ├───controller
│   │   │               ├───model
│   │   │               ├───services
│   │   │               │   └───imp
│   │   │               └───util
│   │   └───resources
│   └───test
│       └───java
│           └───com
│               └───money
│                   └───pequenoinvestidor
│                       └───integração
Enter fullscreen mode Exit fullscreen mode

Conhecendo nosso plugin🧐

Utilizaremos a stack qa-stacks, quem tem como objetivo, disponibilizar soluções que acelere e simplifique a abordagem de diferentes metodologias de teste.

Os plugins permitem adicionar novas capacidades à sua aplicação. Neste caso, utilizaremos um plugin presente na qa-stacks que realiza as configurações necessárias para a realização de testes de mutação em projetos java.

Image description

Importante: Essa é uma stack para fins didáticos.

Utilizando o plugin🔌

Para utilizar o plugin mutation-java, é necessário estar dentro do diretório da aplicação desejada. Neste exemplo, a aplicação é o pequenoinvestidor.

cd pequenoinvestidor
Enter fullscreen mode Exit fullscreen mode

Na raiz do projeto, utilizaremos o seguinte comando para aplicar o plugin de configuração de testes de mutação ao projeto:

stk apply plugin qa-tools/mutation-java@0.1.1
Enter fullscreen mode Exit fullscreen mode

Será necessários fornecer algumas entradas para a configuração do plugin. A primeira delas é referente ao gerenciador de dependências utilizado no projeto. O plugin da suporte a projetos maven e gradle utilizando groovy. Nesse exemplo utilizaremos maven.

? Qual gerenciador de dependenciais do projeto?
 » 1) Maven
   2) Gradle
  Answer: 1) Maven
Enter fullscreen mode Exit fullscreen mode

A próxima informação que você precisa fornecer é referente à biblioteca de logs utilizada no projeto. No projeto pequeno investidor, está sendo utilizada a biblioteca org.slf4j.Logger.

? Qual lib de logs utilizada no projeto? (Use shortcuts or arrow keys)
   1) java.util.logging
   2) org.apache.log4j
 » 3) org.slf4j
   4) org.apache.commons.logging
  Answer: 3) org.slf4j

Enter fullscreen mode Exit fullscreen mode

Trechos de logs podem interferir nos resultados do teste de mutação, precisamos informar para a ferramenta pitest ignora trechos de log por meio da configuração avoidCallsTo.

Em seguida, você precisará informar qual é a cobertura de mutantes esperada para o projeto após a execução dos testes de mutação. Como o projeto pequeno investidor possui baixa cobertura de testes unitários, vamos informar o valor de 50%.

 Qual cobertura de mutantes esperada?(1% a 99%) 
Enter fullscreen mode Exit fullscreen mode

A cobertura de mutantes é definida como a porcentagem de mutantes mortos pelo número total de mutantes gerados: (Mutantes Mortos / Número Total de Mutantes) * 100. É um excelente indicador para avaliar se os testes unitários estão conseguindo identificar os mutantes. Taxas elevadas de mutantes sobreviventes resultam em baixa cobertura de mutantes.

A seguir você precisara informar qual o grupo de mutantes será configurado no seu projeto. Essa é uma informação referente a quantidade de variações/tipos de mutantes que serão gerados. Por padrão a ferramenta pitest considera os mutantes OLD_DEFAULTS, no entanto vamos selecionar a opção DEFAULTS:

? Grupo de mutantes a ser utilizado?
   1) OLD_DEFAULTS
 » 2) DEFAULTS
   3) STRONGER
   4) ALL
  Answer: 2) DEFAULTS
Enter fullscreen mode Exit fullscreen mode

Mais detalhes sobre as mutações geradas no código da aplicação com base no grupo escolhido podem ser conferidas em mutators .

Chegamos a duas informações extremamente importantes. Primeiramente, precisamos informar ao Pitest o pacote onde se localizam as classes de negocio da nossa aplicação, para que a ferramenta possa gerar os mutantes. Embora pudessemos simplesmente informar com.* para que a ferramenta gere mutantes para todas as classes do projeto, isso não é uma prática recomendada. Neste exemplo, informarei o seguinte pacote com.money.pequenoinvestidor.services.imp.CalculoServiceImp

? Qual o pacote das classes a serem gerados mutantes?com.money.pequenoinvestidor.services.imp.CalculoServiceImp
Enter fullscreen mode Exit fullscreen mode

Nos testes de mutação, é importante estar atento as classes em que as mutações no código serão aplicadas. O objetivo é avaliar se mudanças nas regras de negócio são identificadas pelos testes unitários. Dependendo da arquitetura do projeto, é recomendado concentrarmos nas classes que implementam essas regras de negócio, ignorando interfaces, classes abstratas ou outros pontos do código que podem interferir no resultado dos testes de mutação.

precisamos informar o pacote onde estão localizadas as classes de testes do nosso projeto. Neste exemplo, utilizaremos o pacote de testes com.money.pequenoinvestidor.TestCalculoServiceImp

? Qual o pacote dos testes unitários? com.money.pequenoinvestidor.TestCalculoServiceImp
Enter fullscreen mode Exit fullscreen mode

Ao final do processo, a Stackspot informará que o plugin foi aplicado com sucesso ao projeto:

- Plugin qa-tools/mutation-java@0.1.1 aplicado.
Enter fullscreen mode Exit fullscreen mode

Acessando o arquivo pom.xml do projeto pequeno investido, podemos observar que as configurações para o plugin do pitest foram aplicadas, e as entradas que fornecemos serviram como base para a configuração dos testes de mutação:

<plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M7</version>
                <configuration>
                    <excludes>
                        <exclude>**/FiisTest.java</exclude>
                    </excludes>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.junit.jupiter</groupId>
                        <artifactId>junit-jupiter-engine</artifactId>
                        <version>5.4.0</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.pitest</groupId>
                <artifactId>pitest-maven</artifactId>
                <version>1.5.0</version>
                <configuration>
                    <targetClasses>
                        <param>com.money.pequenoinvestidor.services.imp.CalculoServiceImp</param>
                    </targetClasses>
                    <targetTests>
                        <param>com.money.pequenoinvestidor.TestCalculoServiceImp</param>
                    </targetTests>
                    <mutators>
                        <mutator>DEFAULTS</mutator>
                    </mutators>
                    <outputFormats>
                        <outputFormat>HTML</outputFormat>
                        <outputFormat>XML</outputFormat>
                    </outputFormats>
                    <failWhenNoMutations>false</failWhenNoMutations>
                    <avoidCallsTo>
                        <avoidCallsTo>org.slf4j</avoidCallsTo>
                    </avoidCallsTo>
                    <mutationThreshold>50</mutationThreshold>
                </configuration>
            </plugin>
        </plugins>
Enter fullscreen mode Exit fullscreen mode

Executando os teste de mutação😁

Uma vez que a ferramenta Pitest foi configurada em nosso projeto, podemos executar os testes de mutação com facilidade. Para isso, basta utilizar o seguinte comando com o Maven:

mvn test-compile org.pitest:pitest-maven:mutationCoverage
Enter fullscreen mode Exit fullscreen mode

Teremos uma saída semelhante a esta:

--------------------------------------------------------------------------------
> Total  : 1 seconds
--------------------------------------------------------------------------------
================================================================================
- Statistics
================================================================================
>> Generated 14 mutations Killed 11 (79%)
>> Ran 19 tests (1.36 tests per mutation)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.977 s
[INFO] Finished at: 2024-07-12T18:28:29-03:00
[INFO] ------------------------------------------------------------------------
Enter fullscreen mode Exit fullscreen mode

Podemos observar que apensar de um limite de cobertura de 50% definido, os resultados para a classe CalculoServiceImp foram interessantes, de 14 mutações geradas no código 79% foram identificadas por testes unitários existentes.

O pitest já gera relatórios de saída, e por meio deles podemos identificar alguns pontos como dados de cobertura:

Image description

Os tipos de mutantes que foram gerados com base no grupo escolhido, e alguns detalhes da mutação:

Image description

Conclusão💖

Muito além de escrever testes unitários, precisamos nos preocupar com a qualidade dos testes que são escritos. É aí que entra o teste de mutação, uma técnica poderosa que pode nos ajudar a identificar falhas na lógica do código.

Aqui podemos observar mais um exemplo pratico em que a Stackspot EDP pode ser utilizada para nos auxiliar na parte de testes e qualidade de software. Ressaltando mais um vez o quão simples você pode tornar a configuração de testes de mutação utilizando a ferramenta.✨

Sinta-se à vontade para qualquer dúvida!😀

📩 linkedin
🐱‍👤 github

Quer sabe mais sobre stackspot EDP? vou esta deixando o link para o github oficial onde você pode encontrar os principais contatos para o time da stackspot.✨

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (1)

Collapse
 
rafaelleitao profile image
Rafael L. Oliveira

Excelente post.. muito legal o material com stackspot voltado para qualidade..
Seria possivel usar o K6 com o stackspot para facilitar a configuração do projeto?

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay