DEV Community

Alberto Luiz Souza
Alberto Luiz Souza

Posted on

Gerando Testes Automatizados com IA para Códigos Mais Complexos

Disclaimer

Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de uma aula do curso "Os 3 pilares para escalar sistemas distribuídos" da Jornada Dev + Eficiente. Se preferir acompanhar por vídeo, é só dar o play.

Introdução

A geração de testes automatizados usando inteligência artificial não é uma novidade, mas com o avanço das IAs generativas, novas possibilidades surgiram. No entanto, quando tentamos aplicar essas tecnologias em códigos mais complexos, com múltiplas dependências e caminhos de decisão, os resultados muitas vezes ficam aquém do esperado. Neste post, vamos explorar como melhorar a geração de testes automatizados para códigos complexos usando IA generativa.

O Desafio dos Testes Automatizados com IA

A regra é simples: IAs generativas conseguem gerar testes eficientes para códigos autocontidos, com poucas dependências. Porém, quando enfrentam códigos mais complexos, com muitas dependências e vários caminhos de decisão, elas começam a se perder. Isso acontece porque, mesmo com janelas de contexto cada vez maiores, a IA precisa entender uma árvore de conhecimento muito extensa, o que dificulta a geração de testes realmente úteis.

A Ferramenta Qodo Cover

Recentemente, surgiu uma ferramenta chamada Qodo Cover, inspirada em um paper da Meta. Essa ferramenta promete aumentar a cobertura de testes usando IA generativa combinada com algoritmos padrão para validação das saídas. O processo funciona assim:

  1. A IA gera testes baseados no código de produção
  2. Os testes são compilados para verificar se são sintaticamente corretos
  3. Os testes são executados múltiplas vezes para verificar estabilidade e diminuir a chance de gerar testes flaky
  4. Verifica-se se os testes realmente aumentam a cobertura
  5. O ciclo se repete até atingir a cobertura desejada

O Problema do Contexto Limitado

Ao testar a ferramenta com uma classe relativamente complexa, que possui 5 dependências e diversos fluxos condicionais, surgiram problemas. A ferramenta conseguiu gerar nomes de testes que faziam sentido, mas o código gerado não compilava porque:

  1. A IA não tinha acesso às classes dependentes
  2. Não conhecia detalhes de importação
  3. Tentava instanciar objetos sem saber como construí-los

O problema fundamental é a falta de contexto. A IA estava tentando gerar testes olhando apenas para a classe em questão, sem conhecer as dependências. É como pedir a alguém para escrever um teste sem permitir que a pessoa veja o código das classes relacionadas.

A Solução: Aumentando o Contexto

Para minimizar o problema, utilizei uma abordagem diferente:

  1. Gerei um arquivo de texto contendo o código de todas as classes Java do projeto usando uma ferramenta chamada git2txt
  2. Utilizei o Gemini, que tem uma janela de contexto gigante, para analisar o código completo e criar uma lista com as dependências descrevendo a interface pública de cada classe
  3. Solicitei a geração de testes para a classe específica, adicionando ao contexto as dependências

Os testes gerados compilaram com apenas pequenas correções e, após ajustes mínimos, todos passaram. O ganho de tempo foi significativo em comparação com a escrita manual dos testes.

Sem contar que a qualidade do teste aumentou, já que o código gerado utilizou muito melhor as dependências.

Reduzindo o Uso Excessivo de Mocks

Durante o processo, identifiquei outro problema: o uso excessivo de mocks. Embora seja comum em testes de unidade, o abuso de mocks pode deixar cada vez mais distantes da realidade.

Um exemplo do mau uso aconteceu com uma classe que recebia uma função como argumento.

@Component
public class ExecuteTransaction {

    @Transactional
    public <T> T withReturn(Supplier<T> supplier) {
        return supplier.get();
    }

    @Transactional
    public void withoutReturn(Runnable runnable) {
        runnable.run();
    }
}
Enter fullscreen mode Exit fullscreen mode

Não é necessário nenhum tipo de mock para lidar com essa classe. Basta passar as funções como argumento e tudo vai funcionar corretamente. Essa foi exatamente a abordagem utilizada no final, deixar o teste instanciar o objeto normalmente e pronto :).

E como essa é uma classe de infraestrutura, ainda existia mais de uma definição de expectativa em cima do mock, o que pode aumentar o esforço de entendimento do teste.

Conclusão

A geração de testes automatizados usando IA generativa para códigos complexos é possível, mas requer uma abordagem que forneça contexto suficiente. Ao alimentar a IA com o código completo do projeto e ainda ter uma etapa de geração de contexto com as dependências necessárias, foi possível gerar testes com muito mais qualidade.

Com essas técnicas, foi possível partir de zero e obter uma boa cobertura de testes com o mínimo de alterações manuais, economizando tempo significativo no processo.

Conheça a Jornada Dev + Eficiente

A Jornada Dev + Eficiente é um treinamento focado em fazer você crescer na carreira como uma pessoa cada vez mais especializada em Entregar Software que Gera Valor com o Máximo de Qualidade e Fluidez.

A Jornada pavimenta este caminho através de uma abordagem integrada, trabalhando diversos aspectos que influenciam na qualidade da entrega final, tais como: Engenharia de Requisitos, Design de Código, Arquitetura, Testes etc.

É o único local que você vai encontrar que é 100% focado em fazer você crescer como uma pessoa desenvolvedora de software completa.

Para conhecer mais, acesse https://deveficiente.com

Top comments (0)