使用AI代理测试分布式系统
摘要
AI编码代理的两项技能,用于设计和运行面向分布式及有状态系统的声明驱动测试,生成结构化的测试计划和发现报告,包含9种状态判定和归责分类。
查看缓存全文
缓存时间: 2026/05/20 17:28
shenli/distributed-system-testing 来源: https://github.com/shenli/distributed-system-testing
分布式系统测试技巧
面向AI编码代理的两项技能,用于设计和运行面向声明的分布式及有状态系统测试。
两者共同生成结构化的Markdown测试计划和发现报告,包含9种状态的裁决以及明确的SUT/测试框架/检查器/环境责任分类。评审人员只需阅读这两份产物即可决定是否发布,无需重新运行任何内容。适用于Claude Code、Codex、Copilot CLI、Cursor、Gemini或任何能读取Markdown并运行shell的代理。技能本身是简单的SKILL.md文件,由代理执行;计划和发现报告是输出。一项技能负责设计计划,另一项负责执行。计划从产品的声明出发,生成与这些声明相关的假设,并编写以声明命名的场景,每个场景尝试证伪一个声明。对于一致性关键场景,每个场景还会绑定一个抽象模型(register | queue | log | lock | lease | ledger | ...)、操作历史模式、命名检查器以及带有可观测落地证据的 nemesis。计划最后包含覆盖充分性论证和保守的信心声明。
为什么
对分布式和有状态系统进行测试的默认方式——编写几个集成测试然后就完事——只能发现一小部分在生产中实际上会破坏这些系统的bug:部分网络分区、非确定性并发、崩溃恢复、升级/回滚、重放下的幂等性、时序敏感排序。这些技能强制执行一种基于该领域来之不易的知识的个性化工作流:
- **声明驱动,而非测试驱动。**从产品承诺的内容出发。每个场景在一个故障下证伪一个声明。以声明命名的测试比以设置命名的测试更难被弱化。
- **覆盖充分性是交付物。**计划末尾包含一个论证,说明所选场景足以发布,以及一份诚实的未验证项清单。
- **复用SUT自身的工具箱。**执行技能在发明新内容之前会先发现现有测试、运行手册和故障注入脚手架。
- **模型+历史+检查器,而不仅仅是混沌。**对于安全性、持久性、幂等性、隔离性、顺序或成员关系声明,每个场景会声明一个抽象模型、操作历史模式、命名检查器(线性一致性、可串行化性、会话一致性、不丢失确认、恰好一次、…),以及如何处理模糊结果(超时、未知提交、重试)。混沌加上模型和检查器,而非仅有混沌。
- **不允许静默通过。**每个PASS都必须引用oracle执行证据以及证明故障实际触发的信号。裁决来自9种状态集,因此“混沌脚本干净运行”不能被解读为“声明在故障下幸存”。每个FAIL都带有SUT/测试框架/检查器/环境责任标签,以便重现者能够进入正确的队列。
你得到什么
端到端地,两项技能产生:
testing-plans/<plan-name>.md ← 包含§0–§9的计划(见下文)
test-sessions/<session-timestamp>/
├── session-log.md ← 时间线+工具箱+环境探测
├── logs/ ← 每个场景的stdout/stderr
├── metrics/ ← 指标快照
├── artifacts/ ← 临时测试框架、转储
└── findings/
├── <scenario-id>.md ← 每个场景的裁决(随运行写入)
└── report.md ← 摘要+充分性+信心增量
计划结构(评审人员无需重新运行测试即可阅读并决定是否发布):
0. 架构概要——系统实际存在的状态
1. 范围
1b. 受测声明——核心
1c. 发现缺失的声明——文档↔代码差异
2. SUT模型
3. 现有测试清单——已覆盖的内容
4. 故障模式假设——与声明ID关联
5. 覆盖矩阵——声明×假设
6. 技术选择——从目录中选取
6b. 环境需求
7. 场景——每个以声明命名,包含目标测试文件和骨架
7.M 模型/历史/检查器纪律——当场景证伪的声明属于
{安全性, 持久性, 幂等性, 隔离性, 顺序, 成员关系}时必填:
受测模型、操作历史模式、命名检查器、nemesis+落地证据、
模糊结果处理、缩减计划(SUT/测试框架/检查器/环境责任)
7b. 覆盖充分性论证——为什么这些测试足够
7c. 残余不确定性——哪些仍未验证,以及为何可以接受
7d. 信心声明——评审人员的裁决
8. 本计划未覆盖的内容
9. 未解决问题/后续事项
示例§7.M块(计划摘录)
### 场景 S3: linearizable_append_under_partition
- 若FAIL则证伪:C1(每个已确认的追加操作都是持久且线性一致的),C5(领导者选举在5秒内完成)
- 负载:8个客户端,70%追加/30%读取,5分钟,键倾斜zipf
- 故障:T+60s时隔离当前领导者的不对称分区,持续30s
- Oracle:使用Porcupine对每个键的历史进行线性一致性检查
§7.M(模型/历史/检查器纪律)
- 受测模型:log
- 操作历史:默认11字段模式(操作ID,进程ID,调用/完成时间戳,操作类型,键,输入,输出,错误,超时标记,可见节点,故障时期)。在进程中记录+服务器端审计。
- 检查器:线性一致性(Porcupine)按键,然后根据最终状态检查不丢失确认
- Nemesis + 落地:不对称分区(iptables阻断一个方向)。落地证据 = iptables丢弃计数器在30秒窗口内从0变为14,712,并且raft日志在注入后2秒内发出"leader-lost; starting election"。
- 模糊结果:超时→timeout_marker=true,complete_ts=null,视为可能已成功;重试是共享输入的独立操作。
- 缩减计划:若FAIL,二分故障窗口并固定种子,然后按references/test-case-reduction.md分类SUT/测试框架/检查器/环境。
示例发现报告行
| ID | Verdict | Nemesis 落地证据 | 缩减分类 |
|---|---|---|---|
| S3 | PASS-hardening | iptables ctr 0→14,712; raft 在 T+1.8s 重新选举 | n/a |
| S4 | FAIL-reproducible | 分区已落地;Elle: 键K17上G2-item异常 | SUT |
| S7 | INCONCLUSIVE-fault-not-proven | iptables规则已安装但计数器保持为0——错误的链 | harness |
| S9 | PARTIAL-model | 落地正常;检查器只覆盖了按键,未覆盖跨键 | n/a |
(完整的发现模板包含Oracle、Oracle执行证据、产物链接、与计划对比的充分性部分以及信心增量——见skills/executing-distributed-system-tests/assets/findings-report-template.md。)
安装(一行命令,任何代理)
在任何AI编码代理(Claude Code、Codex、Copilot CLI、Cursor、Gemini或任何能读取Markdown并运行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.
代理会获取INSTALL.md,将仓库克隆到~/.local/share/distributed-testing-skills/,并配置技能(对于Claude Code在~/.claude/skills/下创建符号链接,对于其他代理在~/AGENTS.md中添加指针块)。之后,在机器上向任何代理提问“为这个系统设计一个测试计划“或“执行路径X下的计划“,代理将遵循SKILL.md工作流。
更新
再次粘贴相同的单行指令。INSTALL.md是幂等的:如果安装路径已存在,则执行git pull --ff-only;否则执行git clone。符号链接始终指向克隆的内容,因此会自动获取新版本。~/AGENTS.md指针块使用HTML标记,每次运行时会被干净地替换——不会重复。如果你对克隆的技能有本地编辑,git pull --ff-only会失败;代理将在丢弃之前停止并询问。
手动安装(如果你想查看具体过程)
git clone https://github.com/shenli/distributed-system-testing.git \
~/.local/share/distributed-testing-skills
# Claude Code: 在 ~/.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/executing-distributed-system-tests
# Codex / Copilot CLI / Cursor / Gemini / 其他: 见 INSTALL.md
使用方法
技能安装后,有两种方式驱动它们:
随意提问(Claude Code带自动触发):
Design a project-wide test plan for this codebase.
Execute the plan at ./testing-plans/<plan-name>.md against this codebase.
技能描述会识别自然语言短语,如“design a test plan“、“execute the plan”、“run stability tests”、“design a release validation plan“等。对于特定模式、输出路径或非自动触发代理,USAGE.md提供了每个工作流(设计和执行,及其各自模式)的复制粘贴提示,以及关于范围、环境探测和长时间运行检查点的技巧。
两项技能
designing-distributed-system-tests
遍历仓库,提取产品所做的声明,生成与这些声明关联的假设,从目录中选择技术,并编写结构化的Markdown计划,包含覆盖充分性论证和信心声明。对于一致性关键场景,计划为每个场景填充§7.M块:受测模型、操作历史模式、命名检查器、nemesis+落地证据、模糊结果处理、缩减计划。详情见:history-discipline.md。
两种模式:变更范围(针对特定提交或PR)和项目级(包含现有测试清单和差距分析的整体计划)。
executing-distributed-system-tests
读取计划,发现SUT的工具箱,探测环境,并按照检查点纪律运行场景。每个场景:捕获故障的落地证据,运行“绿色但有问题“和“弱oracle“审计,从verdict-taxonomy.md中的9状态分类法中分配裁决,并在提交前将每个FAIL分类为SUT/测试框架/检查器/环境。生成发现报告,包含与计划对比的充分性评估和信心增量。
两种模式:默认模式(对SUT只读,临时测试框架放置在会话目录下)和作者模式(将计划§7中声明的场景骨架写入SUT以供审查)。
技术目录
从该领域文献中提取的八个参考文件:
| 文件 | 何时使用 |
|---|---|
catalog-index.md | 选择页面——从这里开始 |
jepsen-and-elle.md | 故障下的线性一致性/可串行化性 |
deterministic-simulation.md | 从种子重现bug;异步重载代码 |
chaos-and-fault-injection.md | 真实集群的部分/不对称故障 |
fuzzing.md | 在sanitizers下进行输入或并发模糊测试 |
formal-methods-tla.md | 设计时的协议正确性 |
property-and-metamorphic.md | 代数定律/变形关系测试 |
performance-and-benchmarking.md | 尾延迟/吞吐量/公平性 |
crash-recovery-and-upgrade.md | 持久性、重放、幂等性、混合版本 |
每个文件遵循相同的结构:何时使用、它能检测到什么、它漏掉什么、具体工具、论文、成本信号、计划检查清单。目录索引将症状与参考文件配对。
仓库布局
.
├── plugin.json ← 可选的插件清单
├── README.md ← 本文件
├── INSTALL.md ← 幂等安装/更新(可粘贴)
├── USAGE.md ← 每个工作流的复制粘贴提示
├── LICENSE
├── skills/
│ ├── designing-distributed-system-tests/
│ │ ├── SKILL.md ← 设计工作流
│ │ ├── assets/plan-template.md ← §0–§9,含受控的§7.M
│ │ └── references/ ← 8文件技术目录+索引、
│ │ 常见分布式系统陷阱、
│ │ 历史纪律
│ └── executing-distributed-system-tests/
│ ├── SKILL.md ← 执行工作流
│ ├── assets/
│ │ ├── session-log-template.md
│ │ └── findings-report-template.md ← 9状态裁决+落地证据
│ └── references/ ← oracle模式(检查器选择器+13种模式)、
│ 故障注入方法(22行nemesis分类)、
│ 测试用例缩减(含责任分类)、
│ 绿色但有问题标志(含弱oracle审计)、
│ 发现分类(TaxDC)、
│ 裁决分类(9状态)
├── evals/ ← 两项技能的评估套件
├── verification/ ← 针对AgentDB的实际运行(具体输出)
└── specs/ ← 原始设计规范
状态
早期但已使用。两项技能已针对AgentDB(一个用Rust编写的分布式代理运行时)端到端多次驱动,发现了六个问题(一个P0候选现已关闭,两个P1已作为PR提交,两个仍开放)。随着测试框架经验的积累,技能主体会不断演化;接下来的几次迭代中预计会有对SKILL.mds和模板的小幅更新。
这些运行产生的实际计划输出、会话目录和发现报告位于verification/下,每个运行一个子目录,每个子目录包含一个README.md描述了什么通过、什么失败以及该过程暴露了技能自身的什么信息。
值得注意的运行:
verification/agentdb-fab7d9d/— 针对AgentDB提交fab7d9d(持久化幂等追加重放)的变更范围计划+执行;670行计划,跨所有八个故障模式类别共16个假设。verification/agentdb-jepsen/— 带线性一致性检查的一致性+崩溃恢复运行。verification/agentdb-projectwide-lidev/和-v2— 带完整覆盖矩阵+充分性论证+信心声明的项目级计划。
还有一个评估套件位于evals/下(设计与执行技能各有独立的evals.json)——用于验证迭代之间SKILL.md主体的行为变化。
致谢
技术目录提炼自Andrey Satarin的综合测试分布式系统目录(https://github.com/asatarin/testing-distributed-systems)。支撑该目录的开创性论文包括:
- Yuan et al., “Simple Testing Can Prevent Most Critical Failures” (OSDI’14)
- Gunawi et al., “What Bugs Live in the Cloud?” (SoCC’14)
- Zheng et al., “Torturing Databases for Fun and Profit” (OSDI’14)
- Kingsbury & Alvaro, “Elle: Inferring Isolation Anomalies from Experimental Observations” (VLDB’20)
- Alfatafta et al., “Toward a Generic Fault Tolerance Technique for Partial Network Partitioning” (OSDI’20)
- Lou et al., “Understanding, Detecting and Localizing Partial Failures in Large System Software” (NSDI’20)
- Gao et al., “An Empirical Study on Crash Recovery Bugs in Large-Scale Distributed Systems” (FSE’18)
- Zhang et al., “Understanding and Detecting Software Upgrade Failures in Distributed Systems” (SOSP’21)
- Bornholt et al., “Using Lightweight Formal Methods to Validate a Key-Value Storage Node in Amazon S3” (SOSP’21)
- Newcombe et al., “How Amazon Web Services Uses Formal Methods” (CACM’15)
许可证
MIT
相似文章
我的智能体技能:测试驱动开发
作者分享了一项适用于AI智能体的测试驱动开发技能,旨在改进测试编写,基于Kent Beck的Canon TDD,并提供了GitHub链接。
你的AI代理绿色测试套件实际证明了什么
本文认为,由于输入空间无限且行为非确定性,AI代理使用固定输入和预期输出的标准测试套件并不充分,主张应采用基于属性的测试方法。
自动化智能体评估的实证研究
本文介绍了 EvalAgent,这是一个通过编码领域专业知识来自动化 AI 智能体评估的系统,旨在解决标准编程助手在此任务中的局限性。此外,本文还提出了用于测试评估流程的基准 AgentEvalBench,并展示了在评估可靠性方面的显著提升。
在实际仓库中运行编码代理:代理写完代码后哪些环节会出问题?
本文讨论了工程团队在采用AI编码代理时面临的实际挑战,如任务安全性、上下文检索、输出审查和协调,并提出了一个用于评估的准备度模型。
我为一家中型律所构建了一个多智能体 AI 系统——以下是真正有效(和无效)的做法
作者分享了在律所部署基于 Claude 和 LangGraph 的多智能体 AI 系统时的经验教训,重点介绍了基于置信度评分的任务交接机制的成功应用,以及防止幻觉产生所需的人机协作监管的重要性。