DEV Community

Marlo Henrique
Marlo Henrique

Posted on • Updated on

Configurando testes de mutação utilizando Stackspot🧠

Recentemente, analisamos como a ferramenta Stackspot pode acelerar o processo de automação de testes em um artigo intitulado acelerando o processo de automação de testes utilizando stackspot, onde demonstramos como criar um novo projeto de forma rápida e fácil. Agora a questão é como adicionar configurações de testes usando a Stackspot a um projeto já existente.

Nesse artigo, veremos como podemos realizar a configuração de testes de mutação em um projeto backend já existente utilizando um plugin criado com Stackspot.

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.

Mão na massa👩‍💻

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 está estruturado em 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

Importando nossa stack🧐

Utilizaremos a stack qa-api-stack, que tem como objetivo acelerar a criação de testes de API.

Como vimos anteriormente, os plugins permitem adicionar novas capacidades à sua aplicação. Neste caso, utilizaremos um plugin da stack qa-api-stack que realiza as configurações necessárias para a realização de testes de mutação em seu projeto.

Para instalar a stack, basta utilizar o seguinte comando:

stk import stack https://github.com/marlo2222/qa-api-stack
Enter fullscreen mode Exit fullscreen mode

Após a instalação da stack pela CLI, é possível verificar as stacks disponíveis usando o comando stk list stack.

+------------------+--------+-----------------------------------------------------------+
| name             | type   | description                                               |
+------------------+--------+-----------------------------------------------------------+
| qa-api-stack     | remote | Stack para automaçãoes de API utilizando rest assured.    |
|                  |        |                                                           |
| qa-cypress-stack | remote | stack para a criação de projetos de automação com cypress |
+------------------+--------+-----------------------------------------------------------+
Enter fullscreen mode Exit fullscreen mode

É importante ressaltar que a partir de agora, podemos obter uma lista dos plugins disponíveis nas stacks instaladas usando o comando stk list plugin.

+-------------+-----------------------------------------------------+-----------------+
| name        | description                                         | version(latest) |
+-------------+-----------------------------------------------------+-----------------+
| pitest-java | Plugin para a configuração de testes de mutação com | Sem release     |
|             | a ferramenta pitest em projetos java.               |                 |
+-------------+-----------------------------------------------------+-----------------+
Enter fullscreen mode Exit fullscreen mode

Importante: Essa é uma stack para fins didáticos e que seu principal objetivo, que é a configuração de testes de API, ainda está em desenvolvimento.

Utilizando o plugin🔌

Para utilizar o plugin pitest-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, utilize o seguinte comando para aplicar o plugin de configuração de testes de mutação ao projeto:

stk apply plugin -s qa-api-stack/pitest-java
Enter fullscreen mode Exit fullscreen mode

Um destaque ao argumento -s, ele basicamente ignora a checagem de aplicativos que não foram criados utilizando Stackspot, como é o exemplo do projeto pequeno investidor.

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 para 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 pouca 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 que diz respeito 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 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 estarmos atentos 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 nossos 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-api-stack/pitest-java 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 essa configuraçã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: 2023-04-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 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.✨

E como sugestão, gostaria que vocês tente a configuração em um projeto gradle.😎

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

📩 linkedin
🐱‍👤 github

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

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?