Test contrattuale
1) Dove applicare i contratti
HTTP REST/JSON - Risorse, paginazione, filtri, idipotenza, codici di errore.
gRPC/Protobuf: tipi di messaggi, stati, semantica deadline, backward-compat v.proto.
GraphQL: schemi, no-null, direttive, perimetri sui campi.
Messaggi/striam (Kafka/Pulsar/SQS): schemi event (Avro/JSON/Protobuf), chiavi di partizionamento, ordine, chiavi idimpotenti.
SDK/librerie interne: funzioni pubbliche/esclusioni/contratti di prestazioni.
2) Modello CDC: ruoli e manufatti
Il consumatore pubblica il contratto delle aspettative (richieste/risposte approssimative, matchers di tipo, invarianti).
Il fornitore esegue la verifica dei contratti contro il proprio servizio/adattatore/handler'o.
Il broker di contratti (Pact Broker/Backstage/Artefact-repo) memorizza le versioni, i tag («prod», «staging», «canary») e la matrice di compatibilità «consumer @ v s'provider @ v».
Criterio di rilascio: il provider non è autorizzato se viene violato un contratto prod-appropriato.
3) Cosa fissare nel contratto (HTTP esempio)
Minimo:- Metodo/percorso/parametri/intestazione (abilitato auth, chiave idropotente).
- Il corpo e i tipici matcher (tipo/formato/reggexp/intervalli).
- Codici e struttura degli errori stabile'error _ code '.
- Invarianti semantici: ordinamento, unicità, monotonia «created _ at».
- Attesa non funzionale (opzionale): p95, limiti di dimensione, titoli 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) Contratti per eventi (event-driven)
Schema evento: tipo, versione, id, occurred _ at _ utc, producer, subject, payload.
Invarianti: immutabilità «id» e idampotenza per «(type, id)», ordine all'interno della chiave di partitura, monotonia «sequence».
Schema Registry memorizza l'evoluzione e le regole di compatibilità (backward/forward/full).
Test del contratto della console: replicano gli eventi d'oro e le fasi negative (campi sconosciuti, 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) Evoluzione e compatibilità
Versioni dei contratti: semantica'MAJOR '. MINOR. PATCH (MAJOR - Rompenti).
Regole per REST
Non rompere, non rimuovere i campi, non cambiare il tipo/valore dì error _ code ".
Aggiungere campi di default opzionali; nuovi endpoint invece della magia.
Deprecazione: annuncio, supporto parallelo, rimozione metrica.
GraphQL - Solo aggiungere campi, non-null immettere attraverso le fasi; direttive di deprecazione.
gRPC/Proto - Non utilizzare i numeri di campo; solo aggiungerne di nuovi con optional.
Events: schema «vN»; I concettori devono ignorare i campi sconosciuti (pigrizia).
6) Controlli negativi e invarianti
Negative: tipi non validi, valori non consentiti, parametri conflittuali, limiti superati.
Invariants: ordinamento delle risposte, univocità «id», correttezza «next _ cursor», stabilità della risposta idropotente quando viene ripetuta.
I contratti degli aspetti temporanei: 'created _ at'RFC3339/UTC, la proiezione corretta delle 24 ore locali non fa parte del contratto di trasporto - viene immessa negli invarianti aziendali.
7) Generazione stab e sviluppo locale
Dai contratti vengono generati i fornitori di fornitore per lo sviluppo del consumatore.
Per gli eventi, generatori di messaggi validi/borderline.
I greggi sono contrassegnati dalla versione del contratto e dalla data di assemblaggio. Non è consentita la pubblicazione in provetta.
8) Incorporazione in CI/CD (pipline arbitrale)
1. Consumer CI:
Lint/assemblaggio, generazione di contratti, unit/test-contratto, pubblicazione in contract-broker (tag: 'consumer @ 1. 7. 0`).
2. Provider CI:
Sollevamento del servizio localmente/in un contenitore fetch di contratti rilevanti («prod »/« staging»), verifica e pubblicazione dello stato in broker.
3. Release Gate:
Il deposito del provider viene bloccato se ci sono contratti non rispettati.
4. Nightly Matrix:
Matrice di compatibilità'consumer variations x provider variations '; rapporti e allarmi.
9) Esempi di pratiche di dominio
9. 1 REST: paginazione con cursori (invariante contrattuale)
La risposta contiene «items []», «next _ cursor» (nullable), «limit», «total» (opzionale).
Invarianti: 'len (items) limit', ricomparsa con lo stesso 'cursor', insieme idempotente.
Errore se sono stati impostati contemporaneamente cursor e page.
9. 2 Idampotenza POST
Il contratto richiede il titolo «Idempotency-Key».
Invariante: una nuova richiesta con la stessa chiave restituisce lo stesso «id »/stato.
9. 3 Eventi: garanzie dell'ordine
La chiave di partizionamento del contratto è «partition _ key = user _ id».
Invariante: sequence cresce monotono all'interno della chiave; Il consumatore deve gestire le ripetizioni.
10) Sicurezza e privacy negli appalti
Non includere PDN/segreti in esempi - solo sintetico.
Fissa le intestazioni di protezione obbligatorie: «Authorization», «X-Firma», «Replay-Prevention».
Per i webhoop, il contratto di firma e risposta «2xx »/retrai.
Nei logi di test contratto - maschera i campi sensibili.
11) Strumenti
Pact/Pactflow/Pact Broker - HTTP/Messaggistica contratti, matrice di compatibilità.
OpenAPI/AsyncAPI - Specifiche + test generatori (Dredd, Schemathesis).
Karate/RESTAssured - controlli scenografici dei contratti REST.
Protobuf/gRPC - 'buf', 'protolint', test di compatibilità; Schema Registry per Avro/JSON/Proto nei flussi.
Test di Conformance per l' GraphQL (graphql-compat), test di schema snapshot.
12) Pseudo-codice di verifica del provider (semplificato)
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
«Screenshot Postman è un contratto»: nessuna versione/tipo matchers/convalida automatica.
Oversnaping: il contratto fissa valori precisi invece di tipi/pattern per cadute false.
Un contratto condiviso per diverse regioni/canali: ignora la variabilità (bandiere, regole geo).
Contratti senza broker/matrice, non è possibile capire quali versioni sono compatibili.
La scommessa e2e invece dei contratti è lenta, costosa, instabile.
Nessuna valigetta negativa/invariante, solo la pista verde viene testata.
14) Osservabilità e funzionamento
Esportazione dello stato in broker + dashboard «health contract».
Le nuove cadute del provider anti - prod, la crescita di unknown field negli eventi.
Traccia: «contract _ id», «variante», «decision _ id» nei loghi di verifica.
15) Processo di deprecazione
1. Aggiungi campo/endpoint (non spezzante).
2. Segna il vecchio come «deprecated» nella specifica, annuncia i tempi.
3. Monitorare i consumatori in base ai fogli/broker; gate migratorie.
4. Includi deny shadow in stage (dry-run), quindi enforce.
5. Rimuovi dopo la quota zero di utilizzo e conferma compatibilità.
16) Assegno-foglia architetto
1. I consumatori e i loro proprietari sono identificati? I contratti sono versionati?
2. Ci sono broker e matrice di compatibilità con i tag degli ambienti?
3. Il contratto include negativi e invarianti (idiempotenza, cursori, ordinamento)?
4. Schema Registry configurato per gli eventi e la modalità di compatibilità?
5. Pipline blocca il rilascio del provider in caso di violazione dei contratti prod?
6. È stato descritto il processo di deprecazione e la politica evolutiva?
7. Generati da contratti, generatori di eventi locali?
8. La maschera del PD e i titoli di sicurezza obbligatori sono documentati?
9. Le metriche e gli alert contrattuali sono collegati, ci sono rapporti di drift?
10. I contratti sono controllati in CHI da entrambe le parti (consumer e provider)?
Conclusione
I test contrattuali trasferiscono la verità sulle interazioni nei manufatti versionabili e rendono prevedibili le integrazioni. Il CDC, il broker dei contratti e la disciplina dell'evoluzione degli schemi sostituiscono le «sorprese spezzanti» con un processo gestito: verifiche rapide, invarianti chiari e compatibilità trasparente delle versioni. Questo riduce il costo di e2e, accelera le release e migliora la qualità dell'intera piattaforma.