关于 fable-tdd
fable-tdd 是指导 Agent 先用可信测试证明行为缺失或出错,再以最小改动满足测试的开发技能。它要求 RED 确实由目标行为问题导致,并在实现后检查相关边界。
主要功能
- 01明确输入、动作与可观察结果
- 02验证测试环境确实覆盖目标路径
- 03选择能证明行为的测试层级
- 04确认有效 RED 后再改生产代码
- 05检查相邻边界与失败情形
- 06完成后移交新鲜验证证据
适用场景
- 01修复可复现的缺陷或回归
- 02为稳定契约添加新行为
- 03验证输入校验、状态转换或持久化逻辑
- 04重构前为既有不变量建立测试
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ immamdouhaboammar/ get-fable --skill fable-tdd安装后在 Claude Code 中输入/fable-tdd确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
skill.package.jsonagents/openai.yamlevals/scenarios.jsonexamples/failing-test-first.mdreferences/red-green-refactor.mdtest-strategy-and-hard-cases.mdtemplates/tdd-cycle.template.md详细介绍
Fable TDD
在修改生产代码前,先证明行为缺失或已损坏,然后以最小改动满足正确层级上的正确测试。
使命
TDD 不是“先随便写一个失败的测试”。红色状态必须通过可信的测试框架,证明预期行为存在缺口。语法错误、损坏的测试夹具、过时的构建产物或仅针对模拟对象的预期,都不能成为修改生产代码的理由。
此 Skill 致力于优化三件事:
- 因果可信度:测试失败是因为行为不正确;
- 最小干预:实现只修改行为所需的部分;
- 持久的回归证明:如果缺陷再次出现,测试能够捕获。
适用场景
- 修复可复现的错误或回归;
- 添加契约足够稳定、可以进行断言的行为;
- 更改验证、状态转换、计算、API 行为、持久化或集成语义;
- 重构前需要先通过可执行测试描述不变量的场景。
不适用场景
- 尚无法定位或复现行为(
fable-discover); - 主要的不确定性在于外部 API 的语义(
fable-research); - 更改的是非可执行文档或元数据,没有有意义的行为测试(
fable-execute); - 所需的测试框架本身已损坏,或正在执行过时的产物(
fable-recover)。
更改分类
选择测试前,先对行为进行分类。
| 类别 | 首选证明方式 |
|---|---|
| 纯函数/领域逻辑 | 专项单元测试/属性测试 |
| 边界验证/错误映射 | 在边界处进行单元测试或契约测试 |
| 跨模块交互 | 通过已更改的契约进行集成测试 |
| 数据库/队列/缓存行为 | 在可行时,使用真实的边界进行集成测试 |
| HTTP/CLI/公共 API | 在公共入口处进行契约测试/集成测试 |
| UI 用户流程 | 优先使用组件测试/集成测试;对高价值的跨边界行为使用 E2E 测试 |
| 并发/时序 | 使用确定性的协调测试,而不是依赖休眠碰运气 |
| 接缝不佳的旧有行为 | 在最近的稳定边界进行特征化测试 |
| 重构/不应改变行为 | 移动代码前,先编写特征化测试/不变量测试 |
使用能够证明真实行为的最低测试层级,且不要通过模拟消除被测对象本身。
流程
阶段 1 — 编写行为契约
说明:
- 初始状态/输入;
- 触发条件/操作;
- 预期的可观察结果;
- 相关副作用;
- 错误/边界行为;
- 必须保持的不变量。
对于错误,请将具体复现步骤与拟议的实现分别记录。
阶段 2 — 验证测试框架
在进入 RED 阶段前,确认所选测试确实执行了相关路径。
适用时检查:
- 源码与构建产物;
- 测试发现/配置;
- 测试夹具的真实性;
- 功能标志/环境变量;
- 模拟边界;
- 异步操作是否完成;
- 清理/隔离;
- 断言观察的是公共行为,而非内部调用次数。
阶段 3 — 选择测试层级
自问:
- 哪种生产代码更改会让此测试再次失败?
- 测试是否经过了缺陷实际所在的契约?
- 我是否通过模拟消除了疑似故障?
- 更窄的测试能否以更确定的方式证明相同的用户可见行为?
如果无法回答第 1 个问题,这个测试很可能不够可靠。
阶段 4 — RED
编写能够体现行为契约的最小测试并运行。
只有满足以下条件,RED 才有效:
- 测试确实执行;
- 失败具有足够的确定性,便于分析;
- 失败信息/状态与预期的行为缺失/损坏相符;
- 失败并非由设置、语法、导入、环境、过时产物或无关的测试污染导致。
如果失败原因不正确,修复测试/测试框架并重复 RED。此时还不要修改生产代码。
阶段 5 — 最小 GREEN
只修改足以满足有效 RED 的最小生产代码范围。
不要:
- 重新设计相邻 API;
- 添加推测性的灵活性;
- 重构无关代码;
- 弱化断言;
- 用模拟对象替代真实行为来通过测试。
持续运行针对性测试,直至 GREEN。
阶段 6 — 相邻证伪
重构前,根据变更探测最接近的失败面:
- 边界、空输入、无效输入;
- 错误路径;
- 状态转换顺序;
- 幂等性、重试;
- 并发、竞态;
- 与先前格式或 API 的兼容性;
- 持久化、事务行为。
只在测试能保护有意义的契约时添加测试;不要为了增加数量而机械地堆积测试。
阶段 7 — 在 green 状态下重构
现在,按需改进结构。分小步重构,并在每次有意义的变更后重新运行受影响的测试。
阶段 8 — 最新交接
记录最终变更,并将工作交接给 fable-verify,同时提供:
- 行为契约;
- 确切的 RED 证据或原因;
- GREEN 命令及结果;
- 新增或变更的测试;
- 变更的生产代码范围;
- 已探测的相邻情况;
- 针对性测试未覆盖的剩余风险。
决策规则
- 生产代码变更前测试就通过了 → 这并不能证明存在所请求的缺陷;应重新设计测试,或确认该行为已存在。
- 测试在断言前报错 → 修复测试框架或测试,而非生产代码。
- Bug 不可复现 → 先控制或观测这种不确定性;重复随机重跑并不能构成可靠的 RED。
- 并发 Bug → 优先使用屏障、闩锁、伪时钟或确定性调度,而非任意休眠。
- 旧代码没有单元测试接缝 → 在引入接缝前,先测试最接近的稳定公共边界;不要仅为追求单元测试上的纯粹而进行大范围重构。
- 无法在本地测试外部依赖 → 只有在根据主要证据确定伪实现必须保留哪些行为后,才使用契约或伪实现。
- 用户要求“直接修补” → 如果要改变可执行行为,就应遵循 RED 流程,除非明确说明并接受没有可行的测试框架。
- 测试预期与当前商定的产品契约冲突 → 不要强行让实现迁就过时的测试;先解决契约问题。
- 测试只断言某个模拟对象被调用 → 除非调用本身就是公共契约,否则应添加可观测的结果或状态证据。
不变量
- 对于可测试的变更,在有效 RED 出现前,不得改变生产行为。
- RED 和 GREEN 必须针对同一行为契约。
- 不得弱化测试以使实现通过。
- 不得通过模拟来绕过可疑的故障机制。
- 最终 GREEN 必须是在最后一次相关变更后重新验证的。
- 重构不得引入超出已接受任务卡范围的行为。
失败分类
RED 错误
失败源于语法、导入、设置、夹具或环境,而非目标行为。应先修复测试框架。
虚假 GREEN
测试通过了,但没有触及真实的失败边界;通常是模拟对象或过期产物绕过了边界。应强化测试或调整测试位置。
不稳定的 RED/GREEN
在没有相关代码变更的情况下,结果发生变化。在将任一状态视为证据之前,应先找出不确定性的来源。
无法测试的旧代码范围
不存在狭窄的测试接缝。先在稳定边界进行特征测试,然后引入由测试支持的最小接缝。
契约不明确
预期行为本身存在争议或不清楚。应回到规划或研究阶段,而不是将猜测写成测试。
实现循环
已有有效 RED,但两种实质相似的修复都失败。停止编辑,并将 RED、尝试过的方案及观察到的失败差异交由 fable-recover 处理。
反模式
- 先编写实现代码,再补写一个立即通过的测试;
- 将任何失败都视为 RED;
- 修改预期输出以匹配当前实现;
- 明明可以断言用户可见的状态,却只断言模拟交互;
- 使用休眠来“测试”竞态条件;
- 尚未验证某个行为,就先构建复杂的测试抽象;
- 尚未完成特征测试,就对旧代码进行大范围重构;
- 明明只有集成边界才能证明行为,却强行编写单元测试;
- 重构后跳过新一轮 GREEN;
- 将覆盖率百分比等同于回归验证。
证据包
Behavior contract:
Test level + why:
RED command/result + expected failure reason:
Production mutation:
GREEN command/result:
Adjacent cases probed:
Refactor mutations:
Final fresh GREEN:
Residual risk / verify next:
完成标准
满足以下条件即表示 TDD 已完成:
- 通过有效的 RED 展示了行为缺口;
- 只有在出现该 RED 后才修改生产代码;
- 针对同一契约观察到聚焦的 GREEN;
- 考虑了有意义的相邻失败场景;
- 重构或最后一次修改后,重新运行了最终测试;
- 向
fable-verify提供了足够的证据,使其能够独立证伪结果。
延伸资源
- 深入策略:
references/test-strategy-and-hard-cases.md - 现有周期参考:
references/red-green-refactor.md - 示例:
examples/failing-test-first.md