banner

Acelere testes de integração com GitHub Copilot

escrito por Wilson Marcos Ferreira Correa

4 minutos de leitura

null

Descubra como acelerar a criação de testes de integração com GitHub Copilot, Spring Boot, PostgreSQL e Testcontainers. Veja exemplos práticos, boas práticas e como a IA pode aumentar a produtividade no desenvolvimento de software.

Testes de integração são fundamentais no ciclo de desenvolvimento de software, pois garantem que os diferentes componentes de um sistema funcionem corretamente quando conectados entre si. Esse tipo de teste exige um conhecimento mais aprofundado da solução, além de bom domínio da modelagem e dos componentes envolvidos. Vale destacar que os testes de integração não substituem os testes unitários, eles são complementares. Enquanto os testes unitários validam regras específicas, os testes de integração verificam o comportamento da solução considerando a interação entre seus componentes.

Neste artigo, vamos mostrar como acelerar o desenvolvimento de testes de integração utilizando o GitHub Copilot. Essa ferramenta de inteligência artificial auxilia desenvolvedores na geração de código a partir do contexto, sendo extremamente útil para acelerar a criação de testes, além de aumentar a produtividade e a consistência. Para a prática, usaremos Spring Boot na construção de um serviço REST, Spring Data JPA para a interação com o banco de dados PostgreSQL e Testcontainers para simular o ambiente de banco durante os testes.

Tecnologias Utilizadas

  • Spring Boot: Framework Java para criar microserviços e aplicativos robustos.
  • Spring Data JPA: Simplifica o uso de JPA (Java Persistence API) para acessar e manipular dados em bancos relacionais.
  • PostgreSQL: Banco de dados relacional, robusto e amplamente utilizado.
  • Testcontainers: Biblioteca que facilita o uso de containers Docker durante os testes, permitindo a criação de ambientes temporários e isolados.
  • GitHub Copilot: Ferramenta de inteligência artificial para acelerar a escrita de código, sugerindo trechos e resoluções para problemas comuns.
  • IntelliJ com plugin do Copilot instalado.

Arquitetura do Sistema

Vamos construir um micro serviço REST simples usando Spring Boot, com um repositório de dados utilizando Spring Data JPA e PostgreSQL como banco de dados. Em seguida, criaremos testes de integração para garantir que nosso serviço e repositório funcionem corretamente.

Estrutura do Projeto

  • Service Layer: Uma camada de serviço que lida com a lógica de negócios.
  • Repository Layer: Usaremos Spring Data JPA para acessar os dados no banco de dados PostgreSQL.
  • Controller Layer: Um controlador REST para expor endpoints HTTP.
  • Testes de Integração: Testes que verificam a integração entre o serviço e o banco de dados.

Criação do projeto Spring Boot

Primeiramente, crie um novo projeto Spring Boot utilizando o Spring Initializr, selecionando as dependências: Spring Web

  • Spring Data JPA
  • PostgreSQL Driver
  • Spring Boot Test
  • Testcontainers

Adicione também as dependências necessárias no build.gradle:

IMG1.png

Configuração do banco de dados PostgreSQL no application-local.yml

Configure o acesso ao banco de dados no arquivo src/main/resources/application-local.yml:

IMG 2.png

Configurações básicas do copilot

Vamos criar um arquivo de regras para que o Copilot possa seguir alguns padrões e que possa gerar o código deste serviço de exemplo. Crie uma pasta com nome GitHub nas pasta base desse projeto. Em seguida, crie um arquivo chamado copilot-instructions.md dentro desta nova pasta. Esse arquivo é muito útil para que o Copilot siga os padrões que desejar e consequentemente ter o código gerado de maneira coerente entre as várias implementações dentro do projeto. Vamos utilizar as instruções abaixo para nosso teste:

IMG 3.png

Geração do código fonte

Acesse o Copilot e altere para o modo Agent, no prompt solicitaremos ao Copilot que gere a estrutura de tabelas que vamos utilizar.

Setup this project to support flyway migrations and generate the initial script to create a procuts schema and a products table with the following fields: id (UUID) as primary key. name (varchar(100)) set this one as unique key. id (UUID) as primary key. name (varchar(100)) set this one as unique key. Setup the configuration file application-local.yml to support jpa defining PostgreSQLDialect and datasource configurations.

Também no modo Agent, vamos solicitar a geração do código fonte.

Create a product package and the packages entrypoint, domain and infrastructure packages inside. Generate a CRUD for the product table exposing a rest api for the product operations.

Ao final teremos o código fonte gerado com as camadas solicitadas e os endpoints REST que vamos utilizar no teste de integração.

Testes de integração com testcontainers

Testcontainers para Java é uma biblioteca que oferece suporte a testes JUnit, fornecendo instâncias simplificadas ​​de bancos de dados conhecidos e diversas outras ferramentas que possam ser executadas em um container Docker. Vamos solicitar ao Copilot que utilize o framework Testcontainers para a geração dos testes de integração e vamos solicitar que sejam gerados os testes de integração para o controller ProductController que foi gerado anteriormente. Vamos solicitar também que sejam gerados os testes unitários para este projeto.

Setup this project to support testcontainers framework. Generate integration tests for the controller ProductController. Generate unit tests

Os testes foram gerados e o Copilot seguiu corretamente as instruções que colocamos no arquivo copilot-instructions.md.

img.png

Ao executar o teste teremos os seguintes passos:

  • Será inicializado um container com o Postgres, criando um banco de dados vazio para ser utilizado nos testes.
  • Nosso serviço Springboot será inicializado e os scripts de migration serão executados pelo Flyway.
  • O teste enfim é executado.

Refactoring

O arquivo gerado, ProductControllerIntegrationTest possui a configuração base para o Postgres e o ContextInitializer. Esse trecho poderia estar em uma classe base para que possa ser reaproveitado em outros testes de integração que possam ser gerados no futuro. Para deixar mais organizado, vamos solicitar ao Copilot que faça a extração das configurações comuns em uma classe base e faça a alteração do ProductControllerIntegrationTest para que utilize a classe base gerada como herança.

Extract ApplicationContextInitializer from ProductControllerIntegrationTest to a Base class to be reused to new integration classes in the future. Move the class annotations from ProductControllerIntegrationTest to the new base class once it will be reused. Refactor ProductControllerIntegrationTest to extend this new base class.

O Copilot foi capaz de extrair o conteúdo comum em uma classe chamada BaseIntegrationTest e fez as alterações necessárias na classe ProductControllerIntegrationTest, removendo o conteúdo presente na classe base e fazendo a herança.

img 5.png

Problemas conhecidos

O uso do tipo Record no java pode gerar problemas onde o Copilot eventualmente gera um get para acesso aos atributos. Para os testes de integração utilizamos o TestRestTemplate. Ao mapear a porta para realizar a chamada http o Copilot faz o import incorreto do LocalServerPort.Foi necessário corrigir o pacote informado de import org.springframework.boot.web.server.LocalServerPort; para import org.springframework.boot.test.web.server.LocalServerPort; Pouco contexto gera resultados aleatórios. Procure dar a maior quantidade de informações possível ao Copilot para ter um resultado melhor.

Considerações finais

O Copilot é um exemplo prático de como os LLM´s estão mudando a maneira como estamos escrevendo código. A ferramenta demonstrou ser capaz de gerar código e fazer melhorias em um código existente. Foi capaz também de gerar os testes unitários rapidamente. Com exceção do setup inicial do projeto Springboot, praticamente todo este exemplo foi criado utilizando o Copilot.

Em projetos existentes é possível solicitar ao Copilot que faça a análise do projeto e preencha o arquivo de instructions acelerando a adoção da ferramenta dentro dos padrões que já utiliza. É possível também dizer ao Copilot exemplos de implementação para que ele siga os padrões utilizados no exemplo informado. Testes mais complexos requerem mais contexto, quanto mais informação passada ao Copilot, mais completo e assertivo será o código gerado. Mesmo em testes unitários pode ser necessário dar instruções específicas para a geração de determinados testes, obtendo uma melhor cobertura e assertividade.

Durante o desenvolvimento dos testes, o GitHub Copilot pode ser utilizado para acelerar a escrita de código. Ele pode sugerir implementações completas de métodos e até trechos de configuração. Por exemplo, ao começar a escrever um teste para a criação de um produto, o Copilot pode sugerir automaticamente o código do teste, o que acelera consideravelmente o processo, deixando o desenvolvedor mais focado em regras complexas.

Clique aqui para acessar o código fonte desse projeto.

Compartilhe esse post: