Teste de contrato
1) Onde aplicar os contratos
HTTP REST/JSON: recursos, paginação, filtros, idempotação, códigos de erro.
gRPC/Protobuf: tipos de mensagens, estatais, semântica 'deadline', backward-compat v.proto.
GraphQL: esquemas, não-null, diretrizes, parafusos em campos.
Mensagens/striptease (Kafka/Pulsar/SQS): circuitos event (Avro/JSON/Protobuf), chaves de partilha, ordem, chaves idimpotentes.
SDK/bibliotecas internas: funções públicas/exceções/contratos de desempenho.
2) Modelo CDC: papéis e artefatos
O consumidor publica o contrato de espera (solicitações/respostas, jogos de tipo, invariantes).
O fornecedor revisa os contratos contra o seu serviço/adaptador/handler 'ov.
O corretor de contratos (Pact Broker/Backstage/artefacto-repo) armazena versões, marcas de formatação ('prod', 'staging', 'canary') e matriz de compatibilidade 'consumer @ v → provider @ v'.
A política de lançamento é proibida quando qualquer contrato prod-relevante for violado.
3) O que fixar no contrato (HTTP exemplo)
Mínimo:- Método/caminho/parâmetros/cabeçalho (afixado auth, chave idempotal).
- Corpo e jogos típicos (tipo/formato/regexp/faixa).
- Códigos e estrutura de erro; estáveis 'error _ código'.
- Invariantes semânticos: triagem, exclusividade, monotonia 'created _ at'.
- Espera não unificada (opcional): p95, limite de tamanho, cabeçalhos rate-limit.
json
{
"interaction": "GET /v1/users/{id}",
"request": { "method": "GET", "path": "/v1/users/123", "headers": {"Accept":"application/json"} },
"matchers": {
"response.body.id": "type:number",
"response.body.email": "regex:^.+@.+\\..+$",
"response.body.created_at": "format:rfc3339"
},
"response": {
"status": 200,
"headers": {"Content-Type":"application/json"},
"body": {"id": 123, "email": "alice@example.com", "created_at": "2025-10-31T12:00:00Z"}
},
"error_cases": [
{
"name":"not_found",
"request":{"path":"/v1/users/9999"},
"response":{"status":404, "body":{"error_code":"USER_NOT_FOUND"}}
}
]
}
4) Contratos de eventos (event-driven)
Esquema de evento: «tipo», «versão», «id», «occurred _ at _ utc», «producer», «subject», «payload».
Invariantes: imutabilidade 'id' e idempotidade por '(tipo, id)', ordem dentro da chave de partição, monotonia 'sequence'.
Schema Registry: armazena a evolução e as regras de compatibilidade (backward/forward/full).
Teste de contrato do Consumer: replica eventos dourados e fases negativas (campos desconhecidos, nullable).
json
{
"type":"record","name":"UserRegistered","namespace":"events.v1",
"fields":[
{"name":"id","type":"string"},
{"name":"occurred_at_utc","type":{"type":"long","logicalType":"timestamp-millis"}},
{"name":"email","type":"string"},
{"name":"marketing_opt_in","type":["null","boolean"],"default":null}
]
}
5) Evolução e compatibilidade
Versões dos contratos: semântica 'MAJOR. MINOR. PATCH '(MAJOR - Quebra).
Regras para o REST:- Não rompa: não remova campos, não mude o tipo/valor de 'erro _ código'.
- Adicione campos opcionais em default; novos endpoint em vez de magia.
- Decolagem: anúncio, suporte paralelo, remoção por métricas.
- GraphQL: campos apenas adicionar, não-null digitar através de fases; diretrizes de depredação.
- gRPC/Proto: não reutilizar números de campos; apenas adicionar novos com optional.
- Events: esquema 'vN'; Os conceituadores são obrigados a ignorar campos desconhecidos (leniência).
6) Verificações negativas e invariantes
Negative: tipos inválidos, valores não permitidos, parâmetros conflitantes, excesso de limites.
Invariants: triagem de respostas, exclusividade de 'id', correção de 'next _ cursor', estabilidade de resposta idumpotente quando repetida.
Os contratos dos aspectos temporários: 'created _ at' RFC3339/UTC, a projeção correta do dia local não faz parte do contrato de transporte - é levada para os invariantes de negócios.
7) Geração de stab e desenvolvimento local
A partir dos contratos são gerados manadas do provedor para o desenvolvimento do consumidor.
Para os eventos, geradores de mensagens «validas/fronteiras» no esquema.
As manadas são marcadas com a versão do contrato e a data de montagem; Não é permitido publicar em proda.
8) Incorporação a CI/CD (arbitragem-pipline)
1. Consumer CI:
Lint/montagem → geração de contratos → unit/contrato-teste → publicação em contract-broker (tag: 'consumer @ 1. 7. 0`).
2. Provider CI:
Levantar o serviço localmente/em um contêiner → o fetch de contratos relevantes ('prod '/' staging') → verificar → publicar o status em broker.
3. Release Gate:
O deplay do provedor é bloqueado se houver contratos não cumpridos.
4. Nightly Matrix:
Matriz de compatibilidade 'consumer versions x provider versions'; relatórios e ansiedades.
9) Exemplos de práticas de domínios
9. 1 REST: paginação com cursores (invariante contratado)
A resposta contém 'items []', 'next _ cursor' (nullable), 'limit', 'total' (opcional).
Invariantes: 'len (items) ≤ limit', recall com o mesmo 'cursor' → conjunto idempotante.
Erro se «cursor» e «page» foram definidos ao mesmo tempo.
9. 2 Idempotidade POST
O contrato requer o título «Idempotency-Key».
Invariante: Uma nova consulta com a mesma chave devolve o mesmo 'id '/status.
9. 3 Eventos: garantias de ordem
A chave de partilha do contrato é 'partition _ key = user _ id'.
Invariante: 'sequence' aumenta monótono dentro da chave; É obrigatório processar as repetições.
10) Segurança e privacidade nos contratos
Não incluir PDN/segredos em exemplos - apenas sintético.
Capturar cabeçalhos de segurança obrigatórios: «Autodeclaração», «X-Mensagem», «Replay-Prevision».
Para webhooks, contrato de assinatura e resposta '2xx '/retrações.
No logs de testes, camuflar campos sensíveis.
11) Ferramentas
Pact/Pactflow/Pact Broker - HTTP/Mensagem contratos, matriz de compatibilidade.
OpenAPI/AsyncAPI - especificações + geradores de teste (Dredd, Schemathesis).
Karate/REST Assured - Verificações cenais de contratos da REST.
Protobuf/gRPC - 'buf', 'protolint', testes de compatibilidade; Schema Registry para Avro/JSON/Proto em fluxo.
Testes de Conformance para GraphQL (graphql-compat), testes de circuito snapshot.
12) Pseudocode de verificação do provedor (simplificado)
python def verify_contract(provider, contract):
for case in contract["cases"]:
req = build_request(case["request"])
res = provider.handle(req) # локально/контейнер assert match_status(res.status, case["response"]["status"])
assert match_headers(res.headers, case["response"].get("headers", {}))
assert match_body(res.body, case["matchers"], allow_extra_fields=True)
for neg in contract.get("error_cases", []):
res = provider.handle(build_request(neg["request"]))
assert res.status == neg["response"]["status"]
assert res.json.get("error_code") == neg["response"]["body"]["error_code"]
13) Anti-pattern
«Screenshots Postman é um contrato»: nenhuma versão/matchers típicos/validação automática.
Oversnaping: O contrato fixa valores precisos em vez de tipos/pattern → baixas falsas.
Um contrato comum para diferentes regiões/canais: ignora variabilidade (bandeiras, regras geo).
Contratos sem corretor/matriz: Não é possível saber quais versões são compatíveis.
Aposta em e2e em vez de contratos: lento, caro, instável.
Nenhuma mala negativa/invariante: apenas a faixa verde é testada.
14) Observabilidade e exploração
Exportar status para broker + dashboard «health contratos».
Alerts: Novas baixas do provedor contra 'prod', crescimento de 'unknown field' nos eventos.
Traçado: 'contract _ id', 'version', 'decision _ id' nos logs de verificação.
15) Processo de despoluição
1. Adicionar campo/endpoint (não quebra).
2. Marcar o antigo como 'deprecated' na especificação, anunciar o prazo.
3. Monitorar os consumidores através de logs/corretores; guidas migratórias.
4. Incluir deny «shadow» em um stage (dry-run) e, em seguida, enforce.
5. Remover após zero uso e confirmação de compatibilidade.
16) Folha de cheque do arquiteto
1. Os consumidores e os proprietários são identificados? Os contratos são versionizados?
2. Há um broker e uma matriz de compatibilidade com marcas de ambientes?
3. O contrato inclui negativos e invariantes (idiempotidade, cursores, triagem)?
4. O modo de compatibilidade do Schema Registry está configurado para eventos?
5. O Pipeline bloqueia o lançamento do provedor quando os contratos de prod são violados?
6. Descrito o processo de depredação e a política de evolução?
7. Geram-se manadas de contratos, há geradores de eventos locais?
8. Camuflagem de PD e cabeçalhos de segurança obrigatórios documentados?
9. As métricas/alertas estão conectadas, há relatórios de drift?
10. Os contratos são verificados em CI em ambas as partes (consumer e provider)?
Conclusão
Os testes contratuais transferem a «verdade» sobre as interações em artefatos versionáveis e tornam a integração previsível. O CDC, o corretor de contratos e a disciplina de evolução dos esquemas substituem as «surpresas quebrantes» por um processo controlado: verificações rápidas, invariantes claros e compatibilidade transparente de versões. Isso reduz o custo e2e, acelera os lançamentos e melhora a qualidade de toda a plataforma.