Superpowers TDD实践:一次跑通完整的RED-GREEN-REFACTOR循环
【免费下载链接】superpowersAn agentic skills framework & software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowers
修bug最怕的就是:这一下改好了,那一下又改出个新的。测试驱动开发(TDD)就是为防这件事而生的。本文拿 Superpowers 项目的真实约定,带你完整走一遍 RED-GREEN-REFACTOR 循环:怎么写一个"预期失败"的测试、怎么写刚好通过的代码、怎么安全地改代码;再附上三类常见场景、常见 TDD 误区,以及一份 TDD 新手教程级的动手指南。
什么是RED-GREEN-REFACTOR:一句话看懂TDD的铁律
一句话版本:先写测试,看着它失败,再写刚好让它通过的代码,最后在不改变行为的前提下改代码。三步走完,就是一个 TDD 循环:
- RED — 写失败的测试:把功能该有的行为先说清楚,此时功能还没实现,测试必须失败
- GREEN — 写最小实现:不优化、不考虑扩展性,只求把测试变绿
- REFACTOR — 改结构,保行为:测试是安全网,此时整理代码,行为一点不能变
Superpowers 对此定了条铁律:没有失败的测试,就不要编写生产代码。写不出测试,说明你还没想清楚要做什么。
一次完整TDD循环走查:拿"金额校验"举例
我们来完整过一遍。假设需求是:下单金额不允许为负数。
第一步(RED):写一个必须失败的测试
先用测试语言把期望行为描述出来:
test('rejects a negative amount', () => { const result = checkAmount(-10); expect(result.error).toBe('Amount cannot be negative'); });按项目约定,测试文件命名为test-<skill-name>.sh,放在测试脚本目录下。跑一次:
npm test path/to/test.test.ts它必须失败——因为checkAmount还不存在。如果不失败,说明测试本身有问题,先修测试。
第二步(GREEN):写刚好通过的代码
只写让测试通过的最少代码,多一行都不写:
function checkAmount(value: number) { if (value < 0) { return { error: 'Amount cannot be negative' }; } return { ok: true }; }再跑一次npm test path/to/test.test.ts,这次变绿 🟢。注意:测试没要求"金额上限",这里就别加,那叫过度设计。
第三步(REFACTOR):改结构,保行为
有了测试垫底,现在改代码是安全的。比如把校验规则抽成配置,方便以后加新规则:
const rules = [ { test: (v: number) => v < 0, message: 'Amount cannot be negative' }, ]; function checkAmount(value: number) { for (const rule of rules) { if (rule.test(value)) return { error: rule.message }; } return { ok: true }; }跑一遍测试,必须全部保持绿色。一旦变红,立刻停下回滚,不许"顺手"继续改。
三类常见场景:新功能、修bug、重构
同一个循环,场景不同只是起点不同:
- 开发新功能:从"期望行为"出发。先把想调用的 API 写成测试,断言写得出来,设计就基本成型了
- 修bug:第一步是写一个能复现 bug 的测试(RED)。举个例子:如果
0被误判成非法金额,就先写一条"0 是合法金额"的测试,确认它失败,再修判断逻辑让它变绿,最后整理代码。复现测试写不出来,通常说明你还没看懂这个 bug - 重构:前提是测试本来就在通过。改命名、抽函数、消重复,因为行为不变,所以每一步都是"安全"的
容易踩的坑:测试怎么写得出来、又干净
下面几问几答,是实际操作时最常遇到的情况:
- 不知道怎么测?先把你期望的 API 和断言语句写出来;实在写不出来,找同事聊——往往会发现是设计本身要改
- 测试复杂到读不懂?复杂的测试常常是复杂设计的信号,回去简化设计
- 是不是所有依赖都得模拟?优先用依赖注入降低耦合,模拟只在必要时用;测试尽量走真实代码
- 铺垫代码太厚?抽成辅助函数;抽完还厚,说明设计已经过大了
- 测试名起得含糊?名字要描述行为(
test('test1')这种是不允许的),一个测试只验证一件事,名字里出现"和"就该拆 - 测到了实现细节?只关注"它做了什么",不关注"它怎么做的"——测行为,不测代码结构
在Superpowers中三步开始TDD实践
先克隆仓库:
git clone https://gitcode.com/GitHub_Trending/su/superpowers然后读一遍 TDD技能文档,把三个阶段的循环要求和测试质量原则弄清楚。最后挑一个小功能,完整走一遍 RED-GREEN-REFACTOR,再跑测试脚本确认:
cd tests/claude-code ./run-skill-tests.sh其中 run-skill-tests.sh 是批量执行技能测试的入口;写测试时可以直接复用 test-helpers.sh 里的公共辅助函数;想看现有案例,参考 test-subagent-driven-development.sh。
提交前自查清单
- 每个新函数/方法都有对应的测试
- 实现之前亲眼看到过测试失败(而不是想当然认为它会失败)
- 失败的原因是"功能缺失",而不是拼写、语法错误
- 写的是刚好能通过测试的最少代码
- 所有测试通过,输出干净、无错误和警告
- 测试尽量使用真实代码,模拟只出现在必要时
- 边缘情况和错误处理都已覆盖
有一条勾不上,就说明流程跑偏了——推倒重来比事后修补更快。TDD 不是形式主义的步骤,而是"先想清楚再动手"的思维方式;下次动手写生产代码前,先问一句:那个失败的测试,写好了吗?
【免费下载链接】superpowersAn agentic skills framework & software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考