AI 코딩 에이전트가 분산 및 상태 유지 시스템을 테스트하기 위한 계획을 수립하고, 실행하여 구조화된 결과 보고서를 생성하는 두 가지 테스트 스킬(Skill)을 소개합니다. 이 방법론은 단순한 통합 테스트가 놓치기 쉬운 네트워크 분할, 동시성, 장애 복구 등 복잡한 버그를 철저히 검증하며, 최종 산출물만으로 리뷰어가 배포 여부를 결정할 수 있게 돕습니다. 클라우드 환경이나 대규모 시스템 안정성을 다루는 엔지니어에게 매우 유용한 접근법입니다.
번역된 본문
분산 시스템 테스트 스킬(Skills)
분산 및 상태 유지 시스템을 위해 AI 코딩 에이전트가 클레임 기반(claim-driven) 테스트를 설계하고 실행하는 두 가지 스킬입니다. 이 두 가지를 함께 사용하면 구조화된 마크다운(Markdown) 테스트 계획과 9단계 평결(verdicts) 상태, 그리고 명시적인 SUT(테스트 대상 시스템) / 하네스 / 체커 / 환경 책임 분류가 포함된 결과 보고서가 생성됩니다. 리뷰어는 이 두 산출물을 읽고 배포(출시) 여부를 결정하며, 다른 것들을 다시 실행할 필요가 없습니다.
Claude Code, Codex, Copilot CLI, Cursor, Gemini 또는 마크다운을 읽고 셸(Shell)을 실행할 수 있는 모든 에이전트와 함께 작동합니다. 이 스킬들은 순수 SKILL.md 파일로 구성됩니다. 에이전트가 이를 실행하며, 계획과 결과 보고서가 최종 출력물입니다. 한 가지 스킬은 계획을 설계하고, 다른 하나는 이를 실행합니다.
계획은 제품의 클레임(주장/보장하는 기능)에서 시작하여 해당 클레임과 연결된 가설을 생성하고, 반증하려는 클레임의 이름을 딴 시나리오를 작성합니다. 일관성이 중요한 시나리오의 경우, 각 시나리오는 추상 모델(register | queue | log | lock | lease | ledger | …)을 작업 내역 스키마(operation-history schema), 명명된 체커, 관찰 가능한 명확한 증거를 가진 네메시스(장애 주입기)에 바인딩합니다. 계획은 커버리지 적절성에 대한 논증과 보수적인 신뢰도陈述로 마무리됩니다.
왜 필요한가?
분산 및 상태 유지 시스템 테스트의 일반적인 기본값인 '몇 가지 통합 테스트를 작성하고 끝내는 것'은 프로덕션 환경에서 이러한 시스템을 실제로 고장 내는 버그 중 극히 일부만 발견합니다. 예를 들어, 부분적인 네트워크 분할, 비결정론적 동시성, 충돌 복구, 업그레이드/롤백, 리플레이 시 멱등성(idempotency), 타이밍에 민감한 순서 지정 등이 있습니다.
이러한 스킬들은 해당 분야의 어렵게 얻은 지식을 끌어와서 독단적이고 명확한 워크플로우를 강제합니다.
테스트 주도가 아닌 클레임 주도(Claim-driven): 제품이 약속하는 것에서 시작합니다. 모든 시나리오는 하나의 결함(fault) 하에서 하나의 클레임을 반증합니다. 클레임의 이름을 딴 테스트는 설정 이름을 딴 테스트보다 약화시키기 더 어렵습니다.
커버리지 적절성은 필수 산출물: 계획은 선택한 시나리오가 출시하기에 충분하다는 논증과 검증되지 않은 상태로 남는 항목에 대한 정직한 목록으로 끝납니다.
SUT 자체 도구 상자 재사용: 실행 스킬은 새로운 것을 발명하기 전에 기존 테스트, 런북(runbooks) 및 결함 주입 스캐폴딩을 찾아 활용합니다.
카오스(Chaos)가 아닌 모델 + 내역 + 체커: 안전성, 내구성, 멱등성, 격리, 순서 지정 또는 멤버십 클레임의 경우, 모든 시나리오는 추상 모델, 작업 내역 스키마, 명명된 체커(선형성, 직렬성, 세션 일관성, 유실된 응답 없음, 정확히 한 번 등)를 선언하고 모호한 결과(타임아웃, 알 수 없는 커밋, 재시도)를 처리하는 방법을 명시합니다. 단순한 카오스가 아니라 카오스와 모델 및 체커의 결합입니다.
조용한 통과(Pass) 없음: 모든 통과(PASS)는 오라클 실행 증거와 결함이 실제로 발생했음을 증명하는 신호를 인용합니다. 평결은 9개 상태 세트에서 제공되므로 '카오스 스크립트가 깔끔하게 실행되었습니다'가 '클레임이 결함에서 살아남았다'로 잘못 읽힐 수 없습니다.
모든 실패(FAIL)는 SUT / 하네스 / 체커 / 환경 책임 태그를 가집니다: 재현 스크립트가 올바른 담당자에게 전달될 수 있도록 합니다.
결과물
엔드투엔드로 두 스킬은 다음과 같은 결과물을 생성합니다:
testing-plans/.md ← §0–§9가 포함된 계획 (아래 참조)
test-sessions//
├── session-log.md ← 타임라인 + 도구 상자 + 환경 프로브
├── logs/ ← 시나리오별 stdout/stderr
├── metrics/ ← 메트릭 스냅샷
├── artifacts/ ← 임시 하네스, 덤프
└── findings/
├── .md ← 시나리오별 평결 (실행 진행에 따라 작성됨)
└── report.md ← 요약 + 적절성 + 신뢰도 변화
계획 구조 (리뷰어는 테스트를 다시 실행하지 않고도 이것을 읽고 배포 여부를 결정할 수 있습니다):
아키텍처 요약 — 실제 존재하는 시스템 그대로의 모습
범위
1b. 테스트 중인 클레임 — 핵심 척도
1c. 발견된 누락된 클레임 — 문서 ↔ 코드 불일치
SUT(테스트 대상 시스템) 모델
기존 테스트 인벤토리 — 이미 커버된 것
장애 모드 가설 — 클레임 ID에 연결됨
커버리지 매트릭스 — 클레임 × 가설
기법 선택 — 카탈로그에서 선택
6b. 환경 요구 사항
시나리오 — 각각 클레임의 이름을 따르며, 대상 테스트 파일 + 스켈레톤 포함
7.M 모델 / 내역 / 체커 — 시나리오가 다음 클레임 {안전성, 내구성, 멱등성, 격리, 순서 지정, 멤버십}을 반증할 때 필수 항목: 테스트 중인 모델
Distributed Systems Testing Skills Two skills for AI coding agents that design and run claim-driven tests for distributed and stateful systems. Together they produce a structured Markdown test plan and a findings report with 9-state verdicts and an explicit SUT / harness / checker / environment blame classification. A reviewer reads the two artifacts and decides whether to ship; nothing else has to be re-run. Works with Claude Code, Codex, Copilot CLI, Cursor, Gemini, or any agent that reads Markdown and runs shell. The skills are plain SKILL.md files. The agent executes them; the plan and findings report are the output. One skill designs the plan. The other runs it. A plan starts from the product's claims, generates hypotheses tied to those claims, and writes scenarios named after the claim each tries to falsify. For consistency-critical scenarios, each scenario also binds an abstract model ( register | queue | log | lock | lease | ledger | … ) to an operation-history schema, a named checker, and a nemesis with observable landing evidence. The plan ends with a coverage adequacy argument and a conservative confidence statement. Why The default for testing distributed and stateful systems — write a few integration tests and call it done — finds a small fraction of the bugs that actually break these systems in production: partial network partitions, non-deterministic concurrency, crash-recovery, upgrade/rollback, idempotency under replay, timing-sensitive ordering. These skills enforce an opinionated workflow that pulls from the field's hard-won knowledge: Claim-driven, not test-driven. Start from what the product promises. Every scenario falsifies one claim under one fault. A test named after its claim is harder to weaken than one named after its setup. Coverage adequacy is a deliverable. The plan ends with an argument that the chosen scenarios are enough to ship, plus an honest list of what stays unverified. Reuse the SUT's own toolbox. The execute skill discovers existing tests, runbooks, and fault-injection scaffolding before inventing anything new. Model + history + checker, not just chaos. For safety, durability, idempotency, isolation, ordering, or membership claims, every scenario declares an abstract model, an operation-history schema, a named checker (linearizability, serializability, session-consistency, no-lost-ack, exactly-once, …), and how it treats ambiguous outcomes (timeouts, unknown commits, retries). Chaos plus a model and a checker, not chaos alone. No silent passes. Every PASS cites oracle execution evidence and the signal proving the fault actually fired. Verdicts come from a 9-state set, so "the chaos script ran cleanly" can't be read as "the claim survived the fault." Every FAIL carries a SUT / harness / checker / environment blame tag so reproducers reach the right queue. What you get End-to-end, the two skills produce: testing-plans/<slug>.md ← plan with §0–§9 (see below) test-sessions/<UTC>/ ├── session-log.md ← timeline + toolbox + env probe ├── logs/ ← per-scenario stdout/stderr ├── metrics/ ← metric snapshots ├── artifacts/ ← ephemeral harnesses, dumps └── findings/ ├── <scenario>.md ← per-scenario verdict (written as run proceeds) └── report.md ← summary + adequacy + confidence delta The plan structure (a reviewer can read this and decide whether to ship without re-running the tests): 0. Architectural summary — system as it actually exists 1. Scope 1b. Claims under test — the spine 1c. Missing claims discovered — docs ↔ code drift 2. SUT model 3. Existing test inventory — what's already covered 4. Failure-mode hypotheses — tied to claim IDs 5. Coverage matrix — claim × hypothesis 6. Technique selection — from the catalog 6b. Environment requirements 7. Scenarios — each named after the claim, with Target test file + Skeleton 7.M Model / history / — mandatory when the scenario falsifies checker discipline a claim in {safety, durability, idempotency, isolation, ordering, membership}: model under test, operation-history schema, named checker, nemesis + landing evidence, ambiguous-outcome handling, reduction plan (SUT/harness/checker/env blame) 7b. Coverage adequacy argument — why these tests are enough 7c. Residual uncertainty — what stays unverified, and why ok 7d. Confidence statement — the reviewer's verdict 8. What this plan does NOT cover 9. Open questions / followups Example §7.M block (excerpt from a plan) ### Scenario S3: linearizable_append_under_partition - Falsifies if it FAILs: C1 (every acknowledged append is durable and linearisable), C5 (leader election completes within 5s) - Workload: 8 clients, 70% append / 30% read, 5min, key-skew zipf - Faults: asymmetric partition isolating current leader at T+60s for 30s - Oracle: linearizability via Porcupine over per-key histories §7.M (model / history / checker discipline) - Model under test: log - Operation history: default 11-field schema (op id, process id, invoke/complete ts, op type, key, input, output, error, timeout marker, node seen, fault epoch). Recorded in-process + server- side audit. - Checker: linearizability (Porcupine) per-key, then no-lost-ack against final state - Nemesis + landing: asymmetric-partition (iptables drop one direction). Landing evidence = iptables drop counter goes 0 → 14,712 over the 30s window AND raft log emits "leader-lost; starting election" within 2s of injection. - Ambiguous outcomes: timeouts → timeout_marker=true, complete_ts =null, treated as could-have-succeeded; retries are separate ops sharing input - Reduction plan: if FAIL, bisect fault window + fix seed, then classify SUT / harness / checker / environment per references/test-case-reduction.md Example findings-report row ID Verdict Nemesis landing evidence Reduction class S3 PASS-hardening iptables ctr 0→14,712; raft re-election at T+1.8s n/a S4 FAIL-reproducible partition landed; Elle: G2-item anomaly on key K17 SUT S7 INCONCLUSIVE-fault-not-proven iptables rule installed but counter stayed 0 — wrong chain harness S9 PARTIAL-model landing ok; checker covered per-key, not cross-key n/a (The full findings template carries Oracle, Oracle execution evidence, artifact links, an adequacy-vs-plan section, and a confidence delta — see skills/executing-distributed-system-tests/assets/findings-report-template.md .) Install (one line, any agent) Paste this at any AI coding agent (Claude Code, Codex, Copilot CLI, Cursor, Gemini, or anything else that reads Markdown and runs shell): Read https://raw.githubusercontent.com/shenli/distributed-system-testing/main/INSTALL.md and follow the instructions to install and configure distributed-testing-skills for this agent. The agent fetches INSTALL.md , clones the repo to ~/.local/share/distributed-testing-skills/ , and wires the skills in (symlinks under ~/.claude/skills/ for Claude Code, a pointer block in ~/AGENTS.md for other agents). After that, ask any agent on the machine to "design a test plan for this system" or "execute the plan at X" and it'll follow the SKILL.md workflow. Update Paste the same one-liner again. INSTALL.md is idempotent: if the install path exists, it does git pull --ff-only ; if not, it does git clone . Symlinks always point at the cloned content so they pick up the new version automatically. The ~/AGENTS.md pointer block uses HTML markers and is replaced cleanly on each run — no duplication. If you have local edits to the cloned skills, git pull --ff-only will fail; the agent will stop and ask before discarding them. Manual install (if you'd rather see what's happening) git clone https://github.com/shenli/distributed-system-testing.git \ ~ /.local/share/distributed-testing-skills # Claude Code: symlink under ~/.claude/skills/ mkdir -p ~ /.claude/skills ln -snf ~ /.local/share/distributed-testing-skills/skills/designing-distributed-system-tests \ ~ /.claude/skills/designing-distributed-system-tests ln -snf ~ /.local/share/distributed-testing-skills/skills/executing-distributed-system-tests \ ~ /.claude/skills/exec