Testes no pipeline
Esta aula aborda a integração de testes no pipeline de CI/CD, explorando os tipos de testes (unitários, integração, E2E), quando executar cada um, como usar qualidade como gate e como medir cobertura. O objetivo é garantir que o pipeline entregue software confiável de forma automatizada.
Nesta aula, vamos explorar como integrar diferentes tipos de testes no pipeline de CI/CD, garantindo que cada commit seja validado de forma automática e eficiente. Testes são a base da confiança no processo de entrega contínua, e saber quando e como executá-los é fundamental para um pipeline robusto.
Veremos os três grandes grupos de testes — unitários, de integração e end-to-end (E2E) —, discutiremos a ordem ideal de execução, como usar a qualidade como gate para impedir que código problemático avance e como a cobertura de código pode ser uma métrica útil, mas não absoluta.
Testes unitários, integração, E2E
Os testes unitários verificam o menor componente isolado do sistema, como uma função ou método. São rápidos, fáceis de manter e devem ser executados a cada commit. Exemplo em Bash para rodar testes unitários com pytest (Python):
# Executar testes unitários com pytest e gerar relatório de cobertura
pytest tests/unit --cov=src --cov-report=term-missing --junitxml=reports/unit.xmlOs testes de integração validam a interação entre componentes, como banco de dados, APIs ou filas. São mais lentos e consomem mais recursos. Exemplo com Docker Compose para subir dependências e rodar testes:
# Subir serviços necessários e executar testes de integração
docker-compose -f docker-compose.test.yml up -d
pytest tests/integration --junitxml=reports/integration.xml
docker-compose -f docker-compose.test.yml downOs testes E2E simulam o usuário final percorrendo fluxos completos. São os mais lentos e frágeis, mas essenciais para validar o sistema como um todo. Exemplo com Cypress:
# Rodar testes E2E com Cypress em modo headless
npx cypress run --headless --browser chrome --reporter junit --reporter-options mochaFile=reports/e2e.xmlQuando rodar cada um
A ordem de execução no pipeline deve refletir o custo e a confiabilidade de cada tipo. Testes unitários são rápidos e devem rodar primeiro, para dar feedback imediato. Se falharem, o pipeline para (fail fast). Exemplo de pipeline no GitLab CI:
stages:
- unit
- integration
- e2e
unit-tests:
stage: unit
script:
- pytest tests/unit
only:
- merge_requests
integration-tests:
stage: integration
script:
- docker-compose up -d
- pytest tests/integration
- docker-compose down
only:
- main
e2e-tests:
stage: e2e
script:
- npx cypress run
only:
- mainTestes de integração e E2E, por serem mais lentos, podem ser executados apenas em branches principais ou antes do deploy. A ideia é balancear feedback rápido com cobertura adequada.
Qualidade como gate
Qualidade como gate significa que o pipeline impede que código de baixa qualidade avance para ambientes superiores. Métricas como cobertura mínima, número de falhas ou tempo de execução podem ser usadas. Exemplo com SonarQube:
# Após rodar testes, analisar com SonarQube e falhar se qualidade não atingir o gate
sonar-scanner -Dsonar.projectKey=meu-projeto -Dsonar.host.url=http://sonarqube:9000 -Dsonar.login=token
# Verificar status do quality gate
curl -u token: "http://sonarqube:9000/api/qualitygates/project_status?projectKey=meu-projeto" | jq -r '.projectStatus.status'
if [ "$status" != "OK" ]; then exit 1; fiOutra abordagem é usar thresholds no próprio pipeline, como exigir cobertura mínima de 80% nos testes unitários. Exemplo com pytest-cov:
# Falhar se cobertura for menor que 80%
pytest tests/unit --cov=src --cov-fail-under=80Isso garante que o código só avance se atender aos critérios definidos pela equipe.
Cobertura
Cobertura de código mede a porcentagem de linhas, branches ou funções executadas pelos testes. Ferramentas como pytest-cov, JaCoCo (Java) ou Istanbul (JavaScript) geram relatórios. Exemplo de configuração no pytest:
# pytest.ini
[pytest]
addopts = --cov=src --cov-report=html:reports/coverage --cov-report=xml:reports/coverage.xmlNo pipeline, a cobertura pode ser publicada como artefato ou enviada para um serviço como Codecov. Exemplo no GitHub Actions:
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: reports/coverage.xml
flags: unittestsÉ importante lembrar que cobertura alta não garante qualidade: testes podem ser mal escritos ou não cobrir cenários importantes. Use a cobertura como guia, não como meta única.
Boas práticas e observações finais
Mantenha os testes unitários rápidos (segundos), os de integração em minutos e os E2E em no máximo 10-15 minutos. Use relatórios centralizados (JUnit XML) para facilitar a análise de falhas. Considere executar testes em paralelo para reduzir o tempo total do pipeline. E lembre-se: o pipeline é um aliado, não um obstáculo; ajuste os gates conforme a maturidade do time.
Referências
- GitLab CI Testing Documentation
- GitHub Actions Testing
- SonarQube Quality Gates
- pytest Documentation
- Cypress E2E Testing
- Codecov Coverage
Exercícios
- Configure um pipeline no GitLab CI que execute testes unitários e de integração, parando se os unitários falharem.
- Adicione um gate de qualidade que falhe o pipeline se a cobertura de testes unitários for menor que 80%.
- Explique por que testes E2E não devem ser executados a cada commit.
- Crie um script Bash que execute testes unitários, de integração e E2E em sequência, parando se algum falhar.
- Usando o SonarQube, explique como configurar um quality gate que exija cobertura mínima de 80%.
stages:
- unit
- integration
unit-tests:
stage: unit
script:
- pytest tests/unit
only:
- merge_requests
integration-tests:
stage: integration
script:
- docker-compose up -d
- pytest tests/integration
- docker-compose down
only:
- mainpytest tests/unit --cov=src --cov-fail-under=80#!/bin/bash
set -e
pytest tests/unit --junitxml=reports/unit.xml
docker-compose -f docker-compose.test.yml up -d
pytest tests/integration --junitxml=reports/integration.xml
docker-compose -f docker-compose.test.yml down
npx cypress run --reporter junit --reporter-options mochaFile=reports/e2e.xml