← Todos os artigos
Engenharia de Software

Testes de Integração em Microsserviços com Docker e Jenkins

Aprenda a estruturar pipelines de CI para testes de integração em microsserviços usando Docker, Docker Compose e Jenkins com ambientes efêmeros.

4 de leitura
Testes de Integração em Microsserviços com Docker e Jenkins
Foto por Jonathan MONCK-MASON

Guia Prático para Automação de Testes de Integração Contínua em Microsserviços com Docker e Jenkins

Arquiteturas baseadas em microsserviços trazem flexibilidade e escalabilidade, mas também adicionam complexidade significativa à fase de validação de software. Garantir que um serviço funcione isoladamente com testes unitários é vital, porém insuficiente: é preciso validar como ele se comporta ao interagir com bancos de dados, brokers de mensageria e APIs de terceiros.

Neste artigo, abordaremos como estruturar um pipeline de Integração Contínua (CI) eficiente utilizando Jenkins e Docker para automatizar testes de integração em projetos de microsserviços.

O Desafio dos Testes de Integração em Microsserviços

Em aplicações monolíticas, os testes de integração geralmente dependem de uma única base de dados ou de poucos componentes auxiliares. Em microsserviços, a realidade muda:

  • Dependências efêmeras: O serviço em teste pode precisar de uma instância limpa do PostgreSQL, de um tópico no Apache Kafka e de um cache no Redis.
  • Isolamento de ambiente: Testes executados em paralelo ou consecutivamente não podem poluir a base de dados de exibições futuras.
  • Reprodutibilidade: O ambiente de testes do servidor de CI (Jenkins) precisa ser idêntico ao ambiente local de desenvolvimento.

O uso de containers Docker resolve o problema da reprodutibilidade e do isolamento, permitindo levantar todas as dependências necessárias em segundos e descartá-las após a execução dos testes.

[IMAGEM] tipo: diagrama assunto: Fluxo do pipeline de CI no Jenkins executando testes de integração em containers Docker motivo: Ilustra visualmente o ciclo de vida dos containers durante a execução do pipeline de integração contínua. [/IMAGEM]

Arquitetura da Solução

A estratégia consiste em utilizar o Jenkins para orquestrar o processo, acionando o Docker Compose para subir o microsserviço junto com suas dependências de infraestrutura. O fluxo padrão é composto pelas seguintes etapas:

  1. Checkout: O Jenkins baixa o código fonte do repositório.
  2. Build de Imagens: Criação da imagem Docker do serviço com as últimas alterações do código.
  3. Provisionamento do Ambiente: Inicialização dos containers de apoio (banco de dados, redes e mocks) via docker-compose.test.yml.
  4. Execução dos Testes: Execução do runner de testes dentro de um container dedicado ou a partir do próprio agente de CI direcionado aos containers ativos.
  5. Coleta de Resultados: Extração dos relatórios de teste e métricas de cobertura.
  6. Teardown (Limpeza): Destruição completa dos containers e volumes para liberar recursos da máquina agente.

Passo a Passo da Implementação

1. Definição do Arquivo Docker Compose para Testes

Para evitar interferência com o ambiente de desenvolvimento local, crie um arquivo dedicado aos testes, por exemplo, docker-compose.test.yml.

Exemplo de configuração com um microsserviço em Node.js e um banco de dados PostgreSQL:

```yaml version: '3.8'

services: postgres-db: image: postgres:15-alpine environment: POSTGRES_DB: app_test POSTGRES_USER: test_user POSTGRES_PASSWORD: test_password ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U test_user -d app_test"] interval: 5s timeout: 5s retries: 5

app-integration-tests: build: context:. dockerfile: Dockerfile.test environment: DB_HOST: postgres-db DB_PORT: 5432 DB_USER: test_user DB_PASS: test_password DB_NAME: app_test depends_on: postgres-db: condition: service_healthy ```

Observe a utilização do bloco healthcheck e da condição service_healthy. Isso garante que o serviço de testes só começará a rodar quando o banco de dados estiver totalmente pronto para aceitar conexões.

2. Criação do Jenkinsfile

O Jenkinsfile abaixo utiliza a sintaxe Declarative Pipeline e garante que, independentemente de os testes passarem ou falharem, o ambiente temporário será destruído na etapa post.

```groovy pipeline { agent any

environment {
    COMPOSE_FILE = 'docker-compose.test.yml'
    PROJECT_NAME = "test_run_${BUILD_NUMBER}"
}

stages {
    stage('Checkout') {
        steps {
            checkout scm
        }
    }

    stage('Preparar e Rodar Testes') {
        steps {
            script {
                // Executa a suíte de testes dentro do container
                sh "docker-compose -p ${PROJECT_NAME} -f ${COMPOSE_FILE} up --build --exit-code-from app-integration-tests"
            }
        }
    }
}

post {
    always {
        script {
            // Limpa os containers, redes e volumes criados nesta execução
            sh "docker-compose -p ${PROJECT_NAME} -f ${COMPOSE_FILE} down -v --remove-orphans"
            // Opcional: remove imagens não utilizadas para economizar disco
            sh "docker image prune -f"
        }
    }
}

} ```

O parâmetro --exit-code-from app-integration-tests faz com que o comando docker-compose up retorne o código de saída (0 para sucesso, diferente de 0 para falha) do container de testes. Isso permite que o Jenkins marque o estágio como correto ou com falha automaticamente.

Boas Práticas e Recomendações

  • Uso do parâmetro de projeto (-p): No Jenkins, onde builds simultâneos podem ocorrer em paralelo na mesma máquina agente, sempre defina um nome de projeto único no Docker Compose utilizando a variável ${BUILD_NUMBER}. Isso evita colisões de nomes de rede e containers.
  • Gestão de Espaço em Disco: Ambientes de CI que executam múltiplos builds em Docker podem lotar o disco rapidamente devido a imagens e volumes órfãos. Certifique-se de executar rotinas de limpeza ou configurar uma rotina com docker system prune -af --volumes periodicamente no nó agente.
  • Testes de Contrato para Dependências Externas: Se o microsserviço interage com outros microsserviços da empresa, prefira utilizar mocks estruturados (como WireMock ou Pact) para evitar a necessidade de subir toda a malha de microsserviços durante o teste de integração de um único componente.

Conclusão

A automação de testes de integração com Docker e Jenkins oferece um ambiente previsível, isolado e facilmente replicável. Ao tratar o ambiente de testes como infraestrutura como código (usando Docker Compose e Jenkinsfile), times de engenharia reduzem drasticamente falhas em produção causadas por desalinhamento de configurações ou incompatividades de dependências.

Fique por dentro das novidades

Receba as principais notícias do DigitalTech por e-mail ou WhatsApp.

Você poderá cancelar a inscrição quando desejar.