Test API contrattuale
1) Perché i test contrattuali
Il contratto registra le aspettative del cliente e le promesse del provider: percorsi/metodi, intestazioni, schemi di corpo, statici, semantiche di errori e vincoli. L'obiettivo è catturare le modifiche incompatibili prima dell'integrazione e rilasciare le versioni in modo sicuro, senza pesanti E2E.
2) Approcci
Consumer-Driven Contracts (CDC) - Il client genera le aspettative (Pact e analoghe). Il provider li confida regolarmente.
Specifica: contratto come fonte unica di verità (SDL); i test convalidano l'implementazione contro la specifica.
Evento: schemi di segnalazione (Avro/JSON Schema/Protobuf) + regole di compatibilità nel broker/registro.
3) HTTP/REST: flusso di specifiche
1. Contratto 3. x (schemi, esempi, codici).
2. Lint e analisi: stile, campi obbligatori, codici uniformi.
3. Convalida di implementazione: generatore di test anti- OpenAPI (approccio schemathesis/Dreedd) + negativi manuali.
4. Snapshot - Registra gli esempi di risposta, la semantica ETag, i titoli di idempotenza.
yaml paths:
/v1/payments:
post:
responses:
"201": { $ref: "#/components/responses/PaymentCreated" }
"409": { description: Duplicate by Idempotency-Key }
"422": { description: Schema/Business validation failed }
4) CDC (Approccio Pact)
Ciclo di vita:1. Consumer sta scrivendo il test e sta formando il file pact (in attesa).
2. Pubblicazione in broker (artefatto).
3. Provider in CI alza il servizio (o il contratto-rack), convalida il pac's.
4. Il broker calcola la matrice di compatibilità can-i-deploy.
Esempio di test consumer (pseudo-JS):js pact
.given("wallet exists")
.uponReceiving("get wallet")
.withRequest({ method:"GET", path:"/v1/wallets/w123", headers:{ "Authorization": term({generate:"Bearer x", matcher:/^Bearer\s.+/}) }})
.willRespondWith({
status: 200,
headers: { "Content-Type": "application/json" },
body: like({ id:"w123", currency: "EUR", balance: 0 })
});
5) Contratti gRPC/Protobuf
Contratto - '.proto'con versioning pacchetti/servizi.
Compatibilità: non riutilizzare i tag, solo aggiungere nuovi tag optional, non eliminare i campi utilizzati; prenotare le camere.
Test: generazione di stub server/client, noleggio valigette automatiche + negativi (unknown fields, size-limits).
6) Contratti di eventi (Kafka/NATS/...)
Схемы: Avro/JSON Schema/Protobuf в Schema Registry.
Criteri di compatibilità: "BACKWARD" (spesso sufficiente) o'FULL ".
Test del produttore: valuta il messaggio contro lo schema; Test del consumatore: accetta la versione precedente e nuova.
Invarianti: chiavi di idampotenza, ordine/ripetibilità, semantica di deduplicazione.
json
{"type":"record","name":"PayoutCreated","fields":[
{"name":"payoutId","type":"string"},
{"name":"amount","type":"double"},
{"name":"currency","type":{"type":"string","logicalType":"iso-4217"}}
]}
7) Compatibilità e versione
Backward-compatibile (minimo consigliato) - Aggiungere campi opzionali, non rompere quelli esistenti.
Forward-compatibile - I consumatori ignorano campi sconosciuti.
Full: entrambe le cose.
Versioning: 'path (/v1)', 'Accept: application/vnd. brand. v2+json`, `proto package v2`.
Criteri di deprecazione - Finestra di output (ad esempio 90 giorni) che avvisa intestazioni/eventi.
8) Negativi e errori è anche un contratto
Standardizzare i codici: 400/401/403/404/409/422/429/5xx, i campi obbligatori «code», «messaggino», «trace _ id».
Dimensioni/limiti - parte del contratto).
Idempotenza: comportamento ripetuto (409 vs 201 same id).
I titoli sono «Retry-After» a 429/503, «Idempotency-Key», «Content-Language», ecc.
json
{ "code":"validation_error", "message":"amount must be ≥ 1", "trace_id":"..." }
9) I dati gestiscono il contratto
Esempi/risposte primitive - vivi, validi in CI.
Le ficsture per CDC sono minime, determinate.
Generazione di dati - property-based per numeri/date; Ma non rompere la stabilità degli snapshot.
10) Pipline in CI/CD (arbitro)
1. Lint/validate: OpenAPI/Proto/Avro (`validate`, style-линер).
2. Publish contratto come artefatto (broker/registro).
3. Verify - Il provider esegue il controllo dei pacchetti CDC/test specifiche.
4. can-i-deploy gate: senza matrice verde rilascio vietato.
5. Verifica che le modifiche siano compatibili (semantic differf).
6. Report: JUNnit/HTML, elenco delle violazioni/descrizioni.
yaml jobs:
lint:...
publish-contract: needs: [lint]
verify-provider: needs: [publish-contract]
can-i-deploy:
if: always()
steps: [run: pact-broker can-i-deploy...]
11) Strumenti (per classe di attività)
Lint/validatori: openapi-linters, protobuf-lint, avro-tools.
CDC: Pact Family/broker, Spring Cloud Contract, Hoverfly (HTTP record/repliche).
Runner specifiche: schemathesis/Dreedd-simile approccio, Postman test + JSON Schema.
Different: semantic-differf OpenAPI/Proto/Avro (identifica le modifiche breaking).
Contenitori: Testcontainers per sollevare il provider/rack dei contratti.
12) Antipattern
«Special doc» è separato dal codice. Tenere il contratto accanto al servizio.
I moki di terze parti, invece del contratto, sono fragili con gli update.
Risposte/generazioni casuali senza riferimento allo schema del flaconcino.
Modifica il tipo o l'obbligatorietà dei campi senza versione.
Estensioni silent senza notifica/deprecazione.
Nessun contratto negativo e nessun codice di errore.
13) Specificità iGaming/finanza
Formalizza i campi di cassa: «amount» - decimale con scala, valuta ISO-4217, invarianti di importo.
Contratti di pagamento/webhoop: HMAC/mTLS, anti-replay ('X-Timestamp' finestra), Idampotenza, 'Retry-After'.
Regionalità/Tenanti: intestazioni obbligatorie «X-Tenant/X-Region», localizzazione dei messaggi.
Eventi: registri invariati (audited), chiavi di deduplicazione, garanzie di consegna (at least once + idipotenti).
14) Esempi di test «scheletri»
14. 1 Schemathesis-stile (pseudo)
bash schemathesis run openapi. yaml --checks all --hypothesis-deadline=200
14. 2 Postman come runner di specifiche
js pm. test ("Scheme/v1/wallets/{ id} is valid," () => {
const schema = pm. collectionVariables. get("wallet_get_schema");
pm. expect(ajv. validate(JSON. parse(schema), pm. response. json())). to. be. true;
});
14. 3 Provider-convalida CDC (pseudo)
bash pact-broker can-i-deploy --pacticipant wallets --version $SHA --to-environment staging
15) Assegno-foglio prod-pronto
- Contratti nel repository, CI valuta e pubblica gli artefatti.
- CDC abilitato per le integrazioni critiche funziona broker/matrix «can-i-deploy».
- Il criterio di compatibilità (HTTP/gRPC/Events) è documentato; semantic-differf automatico.
- Contratti negativi: errori, limiti di dimensione, idampotenza, 'Retry-After'.
- Dati di prova determinati; Gli esempi di esempio sono supportati.
- Versioning e deprecazione: tempi, notifiche, intestazioni.
- Per gli eventi - Schema Registry e modalità compatibilità Il produttore/consumatore sta testando entrambe le versioni.
- Artefatti: JUNnit/HTML, Report diff/verify, matrice di compatibilità.
- Procedura incidente: rapida rollback del contratto/flag Fiech, notifica agli integratori.
16) TL; DR
Fissare le aspettative dei contratti e eseguirli automaticamente: CDC per le aspettative dei client, test specifici per la conformità all'implementazione, registro degli eventi. Mantenere un rigoroso criterio di compatibilità e contratti negativi (errori, limiti, idempotenza). Non è possibile rilasciare senza una matrice verde can-i-deploy e semantic-differf senza modifiche breaking.