
distributed-system-testing — Updated!
Competenze dell'agente AI per il test di sistemi distribuiti
Competenze di Testing per Sistemi Distribuiti
Due competenze per agenti di codifica IA che progettano ed eseguono test guidati da rivendicazioni per sistemi distribuiti e stateful. Insieme producono un piano di test Markdown strutturato e un report dei risultati con verdetti a 10 stati e una classificazione esplicita della colpa SUT / harness / checker / ambiente. Un revisore legge i due artefatti e decide se rilasciare; non è necessario rieseguire nient'altro.
Funziona con Claude Code, Codex, Copilot CLI, Cursor, Gemini o qualsiasi agente che legga Markdown ed esegua shell. Le competenze sono semplici file SKILL.md. L'agente le esegue; il piano e il report dei risultati sono l'output.
Una competenza progetta il piano. L'altra lo esegue. Un piano parte dalle
rivendicazioni del prodotto, genera ipotesi legate a tali rivendicazioni e
scrive scenari nominati in base alla rivendicazione che ciascuno tenta di falsificare. Per
scenari critici per la coerenza, ogni scenario associa anche un modello
astratto (register | queue | log | lock | lease | ledger | …) a uno schema di cronologia delle operazioni,
un checker nominato e un nemesi con prove di atterraggio osservabili. Il piano termina con un
argomento di adeguatezza della copertura e una dichiarazione di confidenza conservativa.
Perché
L'impostazione predefinita per testare sistemi distribuiti e stateful — scrivere pochi test di integrazione e concludere — trova una piccola frazione dei bug che effettivamente rompono questi sistemi in produzione: partizioni di rete parziali, concorrenza non deterministica, crash-recovery, aggiornamento/rollback, idempotenza sotto replay, ordinamento sensibile al tempo.
Queste competenze impongono un flusso di lavoro opinabile che attinge dalla conoscenza duramente conquistata sul campo:
- Guidato da rivendicazioni, non da test. Si parte da ciò che il prodotto promette. Ogni scenario falsifica una rivendicazione sotto un guasto. Un test nominato in base alla sua rivendicazione è più difficile da indebolire di uno nominato in base alla sua configurazione.
- L'adeguatezza della copertura è un risultato. Il piano termina con un argomento che gli scenari scelti sono sufficienti per rilasciare, più un elenco onesto di ciò che rimane non verificato.
- Riutilizza gli strumenti del SUT. La competenza di esecuzione scopre test esistenti, runbook e scaffolding per iniezione di guasti prima di inventare qualcosa di nuovo.
- Modello + cronologia + checker, non solo caos. Per rivendicazioni di sicurezza, durabilità, idempotenza, isolamento, ordinamento o appartenenza, ogni scenario dichiara un modello astratto, uno schema di cronologia delle operazioni, un checker nominato (linearizzabilità, serializzabilità, coerenza di sessione, nessun ack perso, esattamente-una-volta, …) e come tratta gli esiti ambigui (timeout, commit sconosciuti, tentativi). Caos più un modello e un checker, non solo caos.
- Nessun passaggio silenzioso. Ogni PASS cita prove di esecuzione dell'oracolo e il segnale che prova che il guasto è effettivamente scattato. I verdetti provengono da un insieme di 10 stati, quindi "lo script del caos è stato eseguito correttamente" non può essere letto come "la rivendicazione è sopravvissuta al guasto." Ogni FAIL porta un'etichetta di colpa SUT / harness / checker / ambiente in modo che i riproduttori raggiungano la coda giusta.
Cosa ottieni
End-to-end, le due competenze producono:
docs/testing-plans/<slug>.md ← piano con §0–§9 (vedi sotto)
test-sessions/<slug>/<UTC>/
├── session-log.md ← linea temporale + toolbox + sonda ambiente
├── logs/ ← stdout/stderr per scenario
├── metrics/ ← snapshot metriche
├── artifacts/ ← harness temporanei, dump
└── findings/
├── <scenario>.md ← verdetto per scenario (scritto durante l'esecuzione)
└── report.md ← riepilogo + adeguatezza + delta confidenza
La struttura del piano (un revisore può leggerlo e decidere se rilasciare senza rieseguire i test):
0. Riepilogo architetturale — sistema come realmente esiste
1. Ambito
1b. Rivendicazioni sotto test — la spina dorsale
1c. Rivendicazioni mancanti scoperte — deriva documentazione ↔ codice
2. Modello SUT
3. Inventario test esistenti — ciò che è già coperto
4. Ipotesi modalità di guasto — legate agli ID rivendicazione
5. Matrice di copertura — rivendicazione × ipotesi
6. Selezione delle tecniche — dal catalogo
6b. Requisiti ambientali
7. Scenari — ciascuno nominato in base alla rivendicazione, con
File test target + Scheletro
7.M Disciplina modello / — obbligatorio quando lo scenario falsifica
cronologia / checker una rivendicazione in {sicurezza, durabilità,
idempotenza, isolamento, ordinamento,
appartenenza}: modello sotto test, schema
cronologia operazioni, checker nominato,
nemesi + prove di atterraggio, gestione esito
ambiguo, piano di riduzione (colpa SUT/harness/checker/ambiente)
7b. Argomento di adeguatezza copertura — perché questi test sono sufficienti
7c. Incertezza residua — ciò che rimane non verificato e perché ok
7d. Dichiarazione di confidenza — il verdetto del revisore
8. Cosa questo piano NON copre
9. Domande aperte / followup
Esempio blocco §7.M (estratto da un piano)
### Scenario S3: linearizable_append_under_partition
- Falsifies if it FAILs: C1 (ogni append riconosciuta è durevole
e linearizzabile), C5 (elezione leader completata entro 5s)
- Carico: 8 client, 70% append / 30% lettura, 5min, skew chiavi zipf
- Guasti: partizione asimmetrica che isola il leader corrente a T+60s
per 30s
- Oracolo: linearizzabilità tramite Porcupine su cronologie per chiave
§7.M (disciplina modello / cronologia / checker)
- Modello sotto test: log
- Cronologia operazioni: schema predefinito a 11 campi (id op, id processo,
ts invocazione/completamento, tipo op, chiave, input,
output, errore, marcatore timeout, nodo visto,
epoca guasto). Registrato in-process + audit lato server.
- Checker: linearizzabilità (Porcupine) per chiave, poi
nessun ack perso rispetto allo stato finale
- Nemesi + atterraggio: partizione asimmetrica (iptables drop una
direzione). Prova di atterraggio = contatore drop iptables
va da 0 a 14.712 nell'arco di 30 secondi
E il log raft emette "leader-lost; starting
election" entro 2 secondi dall'iniezione.
- Esiti ambigui: timeout → timeout_marker=true, complete_ts
=null, trattato come potrebbe-essere-riuscito;
i tentativi sono op separate che condividono l'input
- Piano di riduzione: se FAIL, biseca finestra guasto + fissa seme, quindi
classifica SUT / harness / checker / ambiente
per references/test-case-reduction.md