Garantindo eficácia na sua suite de testes.

E ai pessoal, tudo bem? Gostaria de compartilhar com vocês, um assunto que não conhecia até eu participar de um...

Data de publicação: 27/09/2019
Você sabe como a Stryker pode te ajudar? Elaboramos esse artigo para explicar como obter eficácia na sua suite de testes com essa ferramenta!

E ai pessoal, tudo bem? Gostaria de compartilhar com vocês, um assunto que não conhecia até eu participar de um evento de JavaScript  em Sorocaba/SP. 

O assunto, como o título já diz, é sobre Testes, vamos ver como a ferramenta Stryker pode nos ajudar a melhorar nossos testes. 

Antes de começar a falar sobre a garantia de eficácia dos nossos testes, acho importante sabermos o real significado que os testes trazem para o seu projeto. 

De várias opções de teste que podemos escolher, temos algum desses na lista 

  • Teste unitário
  • Teste de integração
  • Teste de interface
  • Teste de regressão
  • Teste de sanidade
  • E muitos outros.

Diante de uma variedade tão grande como essa, fui procurar qual seria o melhor teste que eu poderia aplicar em meus projetos. 

Cheguei a conclusão que todos tem lá a sua importância, porém gostaria de compartilhar com vocês, uma imagem para que possamos refletir sobre:

Comparação entre testes
Comparação entre testes.

No começo, achei um tanto estranho, mas faz todo o sentido, no topo dessa quase pirâmide, temos os testes de interface, que são “mais caros” e mais demorados de serem escritos. Porém trazem uma segurança ainda maior para seus testes.

Na base, temos os testes unitários, que são “mais baratos” e rápidos de serem desenvolvidos. 

Com eles ganhamos a prevenção de regressão, onde podemos garantir que nenhuma alteração em uma determinada função afetará diretamente qualquer outra funcionalidade do nosso sistema. 

Testes unitários também incentivam o refactoring do código. Pense no caso onde você está em um sistema antigo, sem nenhum teste escrito e se deparou com uma função que pode ser refatorada. O seu medo e insegurança em fazer um refactoring, será maior do que no caso onde o código seja fortemente testado, visto que, qualquer falha, será apontada na sua suite de testes.

Esses e outros ganhos são resultados de uma suíte de testes. 

Ok, temos a consciência de que os testes são importantes, escrevemos vários testes para a nossa aplicação, porém, a dúvida que paira no ar, como posso garantir que meus testes realmente estão bem escritos?

Para responder a essa pergunta, gostaria de compartilhar uma técnica, chamada testes de mutação.

O teste de mutação, consiste em uma análise por meio da mutação, a fim de produzir novas suites de testes ou evoluir os testes já existentes. 

Com isso, seu objetivo é identificar pedaços de código fracamente testados e testes fracos. 

Basicamente, a técnica consiste em 4 etapas. 

A primeira delas é o operador de mutação, que será aplicado sobre a função original que está sendo testada, realizando pequenas modificações em operadores gerando uma “nova” função, chamada de mutante.

A segunda etapa, é executar os testes originais já escritos, na função originalmente criada, é necessário que seja aprovada em todos os testes. Já a terceira etapa, será executado os mesmos casos de testes já escritos, sobre os mutantes que foram gerados na etapa um. E a temos a seguinte definição, caso o resultado gerados pelos mutantes seja diferente do resultado aplicado sobre a função original, o mutante será morto, e isso é um bom sinal. Porém, caso o resultado do programa original seja igual ao do mutante, ele continuará vivo, o que não é o que queremos. 

A quarta etapa, consiste em você como desenvolvedor analisar o resultado obtido e melhorar sua suíte de testes. 

Podemos ver um exemplo prático, utilizando um repositório de exemplo que eu criei, vou deixar aqui o link do github, https://github.com/eliasreis54/mutation-tests.

E aí, vamos para o hands-on?

Fazendo o clone do repositório com o git: git clone git@github.com:eliasreis54/mutation-tests.git

Você estará na branch master onde o código é bem simples. Se abrir o arquivo index.js, verá a função oldEnough, que tem o propósito apenas de ver se a idade é maior que 18.

Criando um caso de teste comum para isso, onde a cobertura de código será de 100%, temos o seguinte resultado:

Executando o teste, temos o resultado no console:

Detalhes do console
Resultado no console depois de rodar os testes.

 

Aqui entra a grande vantagem do teste de mutação. Se executarmos o stryker, biblioteca utilizada neste exemplo, veremos que ainda há alguns casos de testes que não estamos cobrindo. 

Para ver esse exemplo, basta fazer checkout na branch stryker, que já estará tudo configurado. 

Executando o stryker, temos o seguinte resultado no console: 

Resultado do console
Resultado do console depois de rodar o stryker

 

Como podemos ver, nem todos os mutantes que foram gerados, foram mortos, porque os nossos testes não estão cobrindo todos os casos. Como por exemplo, uma boa suíte de teste, teria um código testando se a idade enviada, fosse igual a 18. 

Como pode ser visto na branch kill-mutants, onde há mais alguns testes escritos de acordo com o resultado da análise de mutação realizada pelo stryker.
Agora, com a última etapa executada, temos o seguinte cenário de teste: 

 

Se executarmos novamente o stryker, veremos que o resultado está bem diferente, agora que temos mais alguns testes escritos:

Resultado do console
Resultado do Stryker no console depois de melhorar a suite de testes.

 

Agora temos 100% dos mutantes mortos, isso significa que temos uma suíte de testes forte, que temos testes escritos para todos os tipos de casos. 

 

Bom, esse foi um exemplo bem simples de aplicação de análise de mutação para melhorar seus testes. Espero ter contribuído para seu aprendizado. 

E se tiver alguma pergunta, comentário ou algum caso parecido e quiser compartilhar, deixe aqui nos comentários desse post, vamos trocar uma ideia! 

 

Abraços e até a próxima. 

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

onze − seis =

Posts relacionados

  1. Sobre a Dextra

    Somos especialistas em desenvolvimento de software sob medida para negócios digitais. Pioneiros na adoção de metodologias de gestão ágil, combinamos processos de design, UX, novas tecnologias e visão de negócio, desenvolvendo soluções que criam oportunidades para nossos clientes.

  2. Categorias

Scroll to top