Testes containers e e2e no Jenkins com Java

TL;DR - Testcontainers sobe Postgres, Redis e o que mais precisar no pipeline; você testa contra dependências reais. No CI, unitários primeiro e containers numa etapa à parte, feedback rápido e confiança de verdade.


Eu queria que os testes do pipeline Java rodassem contra dependências reais (banco, cache, filas) sem depender de um ambiente compartilhado que todo mundo pisa em cima. Testcontainers entra aí: sobe os containers Docker na hora do teste e derruba no fim. Nada de instância única de Postgres no servidor de CI.

flowchart TB
  Jenkins[Jenkins] --> Build[Build Java]
  Build --> Unit[Unit tests]
  Unit --> TC[Testcontainers]
  TC --> Docker[Docker]
  Docker --> DB[(Postgres/Redis)]
  TC --> E2E[E2E]
  E2E --> API[API real]

No Jenkins, o executor precisa ter Docker (ou acesso ao socket). O Maven/Gradle sobe os containers na fase de teste; cada módulo ou suite declara o que precisa. Com JUnit 5 e Postgres: anoto a classe com @Testcontainers, defino o container com @Container e o teste usa a URL que o Testcontainers injeta. Para e2e é o mesmo conceito: sobe a API, o banco e, se fizer sentido, um message broker; o teste faz as requisições e valida o fluxo inteiro.

O preço é tempo. Testes com container demoram mais que unitários puros. No CI eu separo: unitários sempre na frente; Testcontainers e e2e numa etapa seguinte (ou em paralelo), e falha neles bloqueia o merge. O desenvolvedor não fica esperando container subir a cada commit, mas nada sobe sem passar por esses testes.

Na prática, os testes rodavam diariamente em homologação, via Jenkins, depois que as alterações entravam na branch de release. Quando aparecia algum erro, eu adicionava um teste de regressão logo após a correção. Assim o mesmo bug não voltava e a suíte e2e ia ficando cada vez mais representativa do que realmente importa em produção.