关于 agentic-tdd
这是用于 Reticle 的技能,将红—绿—重构 TDD 用于运行中的应用。它要求先定义操作预期结果,并可保存流程用于回归检查。
主要功能
- 01操作前断言预期结果
- 02检查信号、状态、网络和元素
- 03实现后重跑不变的断言
- 04保存流程以供回归复用
适用场景
- 01在实现功能前编写测试
- 02验证保持行为不变的重构
- 03将端到端流程转为回归检查
MCP 相关
Reticle 通过 MCP 提供此技能使用的交互、断言、录制和验证工具。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ reticlehq/ reticle --skill agentic-tdd安装后在 Claude Code 中输入/agentic-tdd确认已加载。
详细介绍
红、绿、重构:针对运行中的应用
单元测试驱动各个单元。它们无法说明“点击 Deploy 后会向 /api/deploy 发送请求、将 store 切换到 deploying,并显示横幅”:只有整个应用运行时,才会出现这种结果。因此,开发循环恰好在最有意思的 bug 出现时停滞,Agent 只能退而求其次,编写代码并寄希望于一切顺利。
这里将同样的纪律提升到更高一层,使用 Reticle 驱动真实应用。还没设置?请按照 reticle 技能操作:它会安装 Reticle,在 init 修改应用文件前征求用户同意,并验证一个流程。
为什么这是 TDD,而不只是事后测试
测试优先的全部价值在于:你尚不知道答案时,就写下预期。看到结果后再写预期,总能调整到与实际情况一致,而 Agent 尤其擅长这种调整。它总能找到一种解读结果的方式,让刚写出的代码看起来是正确的。
reticle_act_and_wait({ ref, action, until }) 在结构上确保了顺序:until 是 action 的参数,因此会在 action 执行前明确写出其结果。这就是真正无法造假的红绿循环。
1. RED:写下预期,看它失败
编写功能前,先说明应用必须实现什么:
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "allOf", predicates: [
{ kind: "net", method: "POST", urlContains: "/api/deploy", status: 200 },
{ kind: "signal", name: "deploy:started" },
{ kind: "element", query: { testid: "deploy-banner" } },
{ kind: "console", level: "error", absent: true },
]}})
这里需要 verified: "no"。**没亲眼看到的红灯,就不是可信的测试。**如果你还没写任何代码,它就返回 yes,说明预期没有针对这次改动写得足够具体。继续收紧预期,直到它因正确的原因而失败。
verified: "unknown" 不代表红灯。这表示 Reticle 无法判断,因此循环完全没有信号。编写代码前先修复这一点,通常只需明确指出应用实际能够产生的结果。
2. GREEN:实现功能,直到同一个调用通过
编写能让预期成立的最小改动,然后重新运行同一个调用,不做任何改动。最后几个字体现了纪律:修改谓词来匹配已实现的内容,会把 TDD 变成事后解说。如果断言必须修改,请明确说明原先的预期为什么有误。
如果结果为 unknown / unsettled,优先重新断言,而不是重新驱动:reticle_assert({ predicate, since, timeout_ms: 8000 })。重新驱动会重复已经发生过的副作用。
3. REFACTOR:让预期成为安全网
现在可以自由修改实现并重新运行。谓词绑定的是行为(请求、信号、状态路径),而不是标记,因此只要重构保留了行为,测试就会继续通过;而基于 DOM 的测试则可能无缘无故地失败。
4. 在下一次改动中继续这个循环
值得优先编写测试的流程,也值得永远重复运行。保存一次即可:
reticle_run({ tool: "reticle_record", sessionId, args: { action: "start", name: "deploy" } })
// drive the journey with reticle_act_and_wait, as in step 1
reticle_run({ tool: "reticle_record", sessionId, args: { action: "stop", name: "deploy" } })
reticle_run({ tool: "reticle_flow_save", sessionId, args: { flowName: "deploy" } })
reticle_run({ tool: "reticle_verify", sessionId, args: { action: "flows" } }) // every saved flow, no model per flow
这样,红绿循环就会变成一套无需手写的回归测试。
应断言的内容,按可靠性排序
- 应用自行发出的信号(
{ kind: "signal" }):应用用自己的语言宣告成功。这是最可靠的选择。 - 状态(
reticle_look { action: "state" }):应用的认知。可捕捉 UI 已变化而 store 未变化的情况。 - 网络:请求、方法和状态码。可捕捉用 mock 代替真实请求的情况。
- 元素出现:必要,但永远不充分。任何内容都可能被渲染出来。
- 没有控制台错误:始终要纳入检查,但绝不能只依赖它。只检查“没有错误”的谓词,在什么都没连接的控件上也会通过。
诚实
**绝不要为了让结果变绿而放宽检查。**在这个循环中,这不是小问题:它会让循环倒着运行,最终得到一套全绿的测试,却无法证明功能正常。
谓词参考:curl https://docs.reticle.sh/predicates.md。其他所有内容:curl https://docs.reticle.sh/llms.txt。