Communitygithub.com

barlevalon/skills

便携式AI辅助工程工作流技能包

skills 是什么?

该技能为AI辅助软件工程工作流提供了一套结构化的测试驱动开发(TDD)实践指南。它强调了“行为变更”必须由“先失败后通过的测试”来证明的核心原则,并提倡通过公共接口而非实现细节来验证行为。技能文档详细描述了RED-GREEN-REFACTOR的迭代工作流、反对水平切片的反模式、针对CLI工具的契约测试策略,以及如何避免常见的合理化陷阱和红旗警告。该技能适用于任何支持AI编码助手(如Claude Code、Cursor、Codex等)的项目,能够帮助开发者建立更加可靠和可维护的测试文化。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add barlevalon/skills

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

测试驱动开发

核心原则

只有当一个测试首先因正确原因失败,然后因实现而通过时,行为变更才值得信赖。

测试应通过公共接口验证行为,而非实现细节。代码可以完全改变,但测试不应改变。

好的测试是集成风格的:它们通过公共API执行真实的代码路径。它们描述的是系统做什么,而非怎么做。好的测试读起来像一份规格说明:“用户可以使用有效购物车结账”精确地告诉了你存在什么能力。这些测试能够经受住重构,因为它们不关心内部结构。

坏的测试与实现耦合。它们模拟内部协作对象、测试私有方法、断言调用次数,或者通过外部手段而非公共接口进行验证。警示信号:重构后行为未变,但测试却失败了。

参见 tests.md、mocking.md 和 testing-anti-patterns.md。

铁律

没有首先编写一个会失败的测试,就不允许有任何受控的生产行为变更。

含义:

  • 为一种行为编写一个测试。
  • 运行它并观察它失败。
  • 确认失败证明了缺失的行为,而非拼写错误/设置错误。
  • 编写能使其通过的最小的生产代码变更。
  • 仅在测试通过后进行重构。

如果实现代码在测试之前已经存在:

  • 未经用户许可,不要删除用户的工作。
  • 将其视为探索原型/参考,而非经过验证的实现。
  • 建议将其搁置一旁,先编写会失败的测试,然后从测试驱动实现。
  • 如果必须保留现有代码,首先添加一个回归/表征测试,然后用一个新的会失败的测试驱动行为变更。

反模式:水平切片

不要先编写所有测试,再编写所有实现。那是水平切片。

错误:

红色:test1, test2, test3, test4
绿色:impl1, impl2, impl3, impl4

正确:

红色 -> 绿色 -> 重构:行为 1
红色 -> 绿色 -> 重构:行为 2
红色 -> 绿色 -> 重构:行为 3

原因:批量测试编码了想象中的设计,超出了反馈循环,而且常常测试的是形状而非行为。

工作流

1. 规划行为

在编写代码之前:

  • 当公共接口变更不明显时,向用户确认。
  • 列出要测试的行为,而非实现步骤。
  • 优先处理关键路径和复杂逻辑;不要追求虚假的完整性。
  • 识别使用 深层模块 的机会。
  • 为 可测试性 设计接口。
  • 选择第一个追踪子弹行为。

提问:“必须存在什么公共行为?哪个行为最重要?”

2. 红色:一个会失败的测试

为一个可观察的行为编写一个最小的测试。

要求:

  • 仅使用公共接口。
  • 名称描述行为。
  • 在可行的情况下测试真实代码。
  • 仅在系统边界或不可避免的接缝处进行模拟。
  • 在实现之前会失败。

运行最有用的精简命令,例如:

npm test path/to/test.test.ts

验证失败:

  • 测试失败,而非由设置/拼写错误导致的错误。
  • 失败原因与缺失的行为匹配。
  • 如果测试立即通过,说明测试有误或行为已存在。修复测试或选择下一个缺失的行为。

3. 绿色:最小实现

只编写足以使当前测试通过的代码。

不要:

  • 添加推测性的功能。
  • 重构不相关的代码。
  • 添加未来的选项。
  • 因为“顺带做一下很容易”而扩大范围。

运行:

npm test path/to/test.test.ts

然后运行相关的周边测试。输出应该干净:没有新的警告、不稳定问题或隐藏的错误。

4. 重构:在通过状态下清理

仅在测试通过后进行重构。如果没有有用的重构,简要说明然后继续。

寻找 重构候选点:

  • 重复
  • 糟糕的命名
  • 浅层模块
  • 混乱的边界
  • 可以隐藏在小接口后面的复杂性

规则:

  • 行为和期望不变。
  • 每次重构步骤后测试保持通过状态。
  • 测试重构可以重命名、去重、提取夹具/构建器,或改进失败消息。
  • 如果断言更改了预期行为,停止:这是一个新的红色循环。

5. 垂直重复

根据上一个循环的反馈选择下一个行为。一次一个行为。

每周期检查清单

[ ] 测试描述可观察的行为,而非实现
[ ] 测试仅使用公共接口
[ ] 测试在实现之前失败
[ ] 失败原因是正确的
[ ] 代码对于此测试是最小的
[ ] 未添加推测性行为
[ ] 相关测试干净通过
[ ] 仅在通过状态下考虑重构

提交闸门

为了可审计的工作,在可行时分开提交各个阶段:

  • 红色提交:仅包含测试或最小脚手架以及会失败的断言。提交信息记录失败的命令和原因。
  • 绿色提交:最小实现。提交信息记录通过的目标测试并提及已考虑重构。
  • 重构提交:无行为或期望变更。提交信息说明发生了什么变化以及什么保持不变。

不要在提交中包含 AI 归属信息。

CLI 契约测试

对于 CLI 工具,命令表面是产品契约。优先采用在最低可靠级别进行的外向内测试:

  1. CLI 契约测试:使用假提供者或夹具执行根/子命令;断言 stdout、stderr、退出行为、JSON 形状。
  2. 单元测试:解析、比较、分类、上下文选择、错误分类。
  3. 提供者集成测试:文件系统夹具和假的外部服务;无需网络/认证。
  4. 生活烟雾测试:仅选择加入;断言形状/不变量,而非波动性精确输出。

手动 QA 回归规则

手动 QA 是发现手段,而非验证支柱。当它发现行为缺口时:

  1. 编写最低级别的红色回归测试来复现它。
  2. 验证失败证据。
  3. 实现绿色。
  4. 重新运行自动化测试。
  5. 仅在测试通过后重新运行手动 QA。

如果输出/文本/CLI 形状发生了变化,添加或更新 CLI 契约测试。

合理化陷阱

说法回应
“太简单了,不用测试”简单的行为仍然会回归。添加一个小测试。
“我之后再测试”之后通过的测试不能证明该测试本可以失败。
“我手动检查过了”手动检查不是可重复的回归测试。
“需要先探索一下”没问题。先探索原型,然后把它放一边,开始 TDD。
“测试很难写”接口可能难以使用。简化接缝/设计。
“模拟让它变得简单”可能是在测试模拟行为。阅读反模式。
“一个大测试就覆盖了”除非端到端契约需要更多,否则优先每个测试一个行为。
“重构需要会失败的测试”纯重构从通过状态开始并保持通过状态;行为变更需要红色阶段。

红旗警告:停止并纠正

  • 在会失败的测试之前进行了生产行为变更。
  • 测试立即通过但声称是红色阶段。
  • 未检查失败原因。
  • 测试名称描述实现。
  • 测试断言私有调用、调用顺序或内部协作对象。
  • 模拟设置主导了测试逻辑。
  • 新增方法仅用于测试。
  • 在绿色阶段修复测试因为实现与测试不一致。
  • 在任何实现之前批量编写测试。

卡住时

问题行动
不知道如何测试编写期望的公共 API 和第一个断言。
测试设置庞大提取夹具/辅助函数;如果仍然庞大,简化设计。
必须模拟一切代码可能耦合度过高。引入依赖注入/接缝。
现有代码没有测试为当前行为添加表征测试,然后为变更编写红色测试。
Bug 不清楚首先手动复现/查看日志,然后编码最小化的回归测试。

完成前验证

  • 新/变更的行为有测试。
  • 每个新行为测试都曾因正确原因被观察到失败。
  • 所有相关测试通过。
  • 测试验证公共行为。
  • 模拟仅限于边界或有正当理由。
  • 未添加仅用于测试的生产 API。
  • 手动 QA 的发现已转化为回归测试。

相关技能