Contract Testing: integração segura com pact
[WIP]
Contexto
Neste RFC quero propor a adoção de Contract Testing como prática para reduzir falhas de integração entre serviços, acelerar releases independentes e tornar a evolução de microsserviços mais segura e previsível.
objetivos:
- Detectar regressões e incompatibilidades entre provedores e consumidores cedo no CI.
- Permitir deploys independentes com baixo risco.
- Reduzir a dependência de testes E2E pesados e frágeis.
- Prover um repositório central de contratos e resultados de verificação.
1. Introdução
Em arquitetura distribuída, é comum exisir trade-offs na comunicação entre serviços. Para conseguir manter uma evolução rápida e independente, é necessario uma forma de garantir que as integrações continuem válidas mesmo quando cada serviço muda de forma isolada.
2. Problema
- Testes manuais lentos e propensos a erro.
- Testes E2E frágeis e custosos.
- Falta de visibilidade sobre quais versões realmente são compatíveis.
- Atraso na evolução de APIs pelo medo de quebrar consumidores.
- ´Quebras de serviços dependentes por causa de mudanças em provider/consumidor
3. Abordagem de Contract Testing
3.1 Provider-driven contracts (PDC)
O provider define o contrato e os consumidores precisam se adaptar.
- Vantagens: controle centralizado, consistência e documentação única.
- Desvantagens: rigidez, dependência do time provedor e atraso no feedback.
3.2 Consumer-driven contracts (CDC)
O consumidor define suas expectativas e o provedor precisa satisfazê-las.
- Vantagens: foco no domínio real, feedback rápido e evolução guiada por uso real.
- Desvantagens: mais complexidade com muitos consumidores, necessidade de coordenação e overhead de testes.
Quando usar?
- PDC: APIs públicas/externas, regras rígidas, quando necessaria governança central.
- CDC: microsserviços internos, equipes autônomas, evolução rápida e múltiplos consumidores.
4. Exemplos
Provider adiciona campo
- PDC: todos os consumidores podem quebrar.
- CDC: só quem usa o campo será afetado.
Provider altera tipo de campo (amount: numeric → string)
- PDC: risco de quebra global.
- CDC: impacto apenas nos consumidores que realmente usam o campo.
5. Desafios técnicos e estratégias
5.1 Versionamento de contratos
Uso versionamento consistente (ex.: incluir commit SHA como consumer-app-version
ao publicar) para evitar race condition e correlacionar pact com builds.
5.2 Estratégias de compatibilidade
- Suportar backward compatibility (campos opcionais).
- Deprecar com timelines e comunicação clara (feature flags, janelas por consumidor).
5.3 Matrix compatibility explosion
Em casos de uso o crescimento da aplicacação e mudança no contrato, cresce a possibilidade de checks: N providers × M consumers × P versões.
Para mitigar:
- Limitar versões suportadas (policy de versões ativas).
- Usar selectors/tags/environments do Pact Broker.
- Automatizar verificação apenas das combinações relevantes.
5.4 Semantic Drift
Definir matching rules para evitar que pequenas variações causem bugs silenciosos.
6. Modulos
- Pact.
- Pact Broker para versionamento, visualização e a famosa “matrix”.
7. Fluxo de trabalho
Consumer CI
- Executa testes com mock provider (Pact) → gera
pact.json
. - Publica pact no Broker (
pact-broker publish
). - Broker dispara webhook para verificação do Provider.
Provider CI
- Recupera pacts do Broker.
- Executa verificação contra seu código.
- Publica resultado no Broker.
Antes do deploy
- Uso
pact-broker can-i-deploy
para checar se é seguro liberar.
8. Exemplos mínimos (conceito)
Consumer test
- Mock provider com interações esperadas.
- Executar código do consumer contra o mock.
- Gerar
pact.json
.
Provider verification
- Baixar pacts do Broker.
- Reproduzir interações contra o provider real.
- Publicar resultados no Broker.
9. Estratégia de implantação
PoC (2–4 semanas)
- Escolher 1 provider crítico e 1–2 consumidores.
- Subir Pact Broker (self-hosted).
- Medir métricas: tempo médio de detecção de quebra, regressões evitadas.
Normas técnicas
- Criação de commiter para: Convenções de naming, provider states, matching rules, branch/tagging.
- Criação de documentação para auxiliaar outros times implantar contract testing
Implantação incremental
- Priorizar times por valor/esforço.
- RFCs por domínio.
- Treinar equipes.
Automação e observabilidade
- Integrar
can-i-deploy
aos pipelines. - Configurar alertas para falhas de verificação.
10. Critérios de aceitação do RFC/POC
- Consumer gera e publica pact automaticamente no CI.
- Provider verifica pacts e publica resultados.
can-i-deploy
funciona corretamente para releases.- Documentação aprovada pelos times.
- Métricas coletadas e comparadas com baseline.