mcpField
F
fable-tdd

fable-tdd

github.com/immamdouhaboammar测试与质量353 次安装1 周前更新
代码仓库

关于 fable-tdd

fable-tdd 是指导 Agent 先用可信测试证明行为缺失或出错,再以最小改动满足测试的开发技能。它要求 RED 确实由目标行为问题导致,并在实现后检查相关边界。

主要功能

  1. 01明确输入、动作与可观察结果
  2. 02验证测试环境确实覆盖目标路径
  3. 03选择能证明行为的测试层级
  4. 04确认有效 RED 后再改生产代码
  5. 05检查相邻边界与失败情形
  6. 06完成后移交新鲜验证证据

适用场景

  1. 01修复可复现的缺陷或回归
  2. 02为稳定契约添加新行为
  3. 03验证输入校验、状态转换或持久化逻辑
  4. 04重构前为既有不变量建立测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/immamdouhaboammar/get-fable --skill fable-tdd

安装后在 Claude Code 中输入/fable-tdd确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

skill.package.json
agents/
openai.yaml
evals/
scenarios.json
examples/
failing-test-first.md
references/
red-green-refactor.md
test-strategy-and-hard-cases.md
templates/
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. 哪种生产代码更改会让此测试再次失败?
  2. 测试是否经过了缺陷实际所在的契约?
  3. 我是否通过模拟消除了疑似故障?
  4. 更窄的测试能否以更确定的方式证明相同的用户可见行为?

如果无法回答第 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

评论

支持 Markdown