测试驱动开发(TDD)是一个简单概念:先写测试,再写代码。但实践中,我们经常偷懒。"这个太简单了,不需要测试"、"先写代码看看效果,测试后面补"、"我已经手动测试过了"。
Superpowers的TDD技能不给你偷懒的机会。这不是建议,是强制执行。
TDD的铁律
Superpowers的TDD技能有一个Iron Law:
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
违反这条规则的后果:
Write code before the test? Delete it. Start over.
No exceptions:
- Don't keep it as "reference"
- Don't "adapt" it while writing tests
- Don't look at it
- Delete means delete
这不是夸张。AI会执行这个规则。
RED-GREEN-REFACTOR流程
TDD的流程是:
- RED:写一个失败的测试
- Verify RED:运行测试,看它失败(确认失败原因正确)
- GREEN:写最小代码让测试通过
- Verify GREEN:运行测试,看它通过
- REFACTOR:清理代码(保持测试通过)
- Repeat:下一个测试
每一步都需要验证。特别是"看测试失败"这一步——这不是仪式,是证明测试有效。
为什么"看测试失败"是必要的
假设你写了一个测试,直接运行,它通过了。你可能想:"很好,测试通过了,可以写代码了。"
但问题是:测试通过了,你不知道它测试了什么。可能是:
- 测试写错了,测试了错误的东西
- 测试太宽松,没有测试关键逻辑
- 测试依赖已有代码(你在重构已有项目)
看测试失败是验证:这个测试确实在测试缺失的功能。失败原因是"功能不存在",不是"测试写错了"。
只有看到测试因正确的理由失败,你才能确定:当你实现功能后,测试通过意味着功能正确。
一个实际案例:添加重试功能
我们看一个Superpowers中的TDD执行过程。
需求:实现一个重试操作的功能,失败时最多重试3次。
传统方式(没有TDD)
开发者可能直接写代码:
async function retryOperation(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (e) {
if (i === maxRetries - 1) throw e;
}
}
}
然后手动测试几次,看起来正常,就认为完成了。
问题:
- 边界情况不确定:第一次成功呢?每次都失败呢?
- 没有自动化验证:以后改代码可能破坏功能
- 不确定行为:重试次数是3还是maxRetries?
Superpowers方式(强制TDD)
AI不会直接写代码。它先写测试:
RED阶段
test('retries failed operations 3 times', async () => {
let attempts = 0;
const operation = () => {
attempts++;
if (attempts < 3) throw new Error('fail');
return 'success';
};
const result = await retryOperation(operation);
expect(result).toBe('success');
expect(attempts).toBe(3);
});
运行测试:
npm test
FAIL: ReferenceError: retryOperation is not defined
AI确认:
Test fails. Failure reason: retryOperation not defined.
This is correct failure: feature missing, not test error.
Proceed to GREEN.
如果测试失败原因是"test syntax error",AI会修复测试,重新进入RED。只有失败原因是"功能缺失",才进入GREEN。
GREEN阶段
AI写最小实现:
async function retryOperation(fn) {
for (let i = 0; i < 3; i++) {
try {
return await fn();
} catch (e) {
if (i === 2) throw e;
}
}
throw new Error('unreachable');
}
注意:这是"最小"实现。没有maxRetries参数(下一个测试才会要求),没有错误类型检查(还没测试),只有让当前测试通过的最小代码。
运行测试:
npm test
PASS
REFACTOR阶段
当前实现已经最小,不需要重构。如果有重复代码或命名问题,AI会在这里清理,但保持测试通过。
下一个测试
AI继续:
test('succeeds immediately without retries', async () => {
let attempts = 0;
const operation = () => {
attempts++;
return 'success';
};
const result = await retryOperation(operation);
expect(result).toBe('success');
expect(attempts).toBe(1);
});
RED → GREEN循环继续。
常见"合理化"及其反驳
Superpowers的TDD技能收集了开发者常见的"合理化":
| Excuse | Reality |
|---|---|
| "Too simple to test" | 简单代码也会出错。测试需要30秒。 |
| "I'll test after" | 测试后通过不能证明什么。 |
| "Tests after achieve same goals" | 测试后验证"写了什么",测试前定义"应该写什么"。 |
| "Already manually tested" | 手动测试没有记录,不能重复运行。 |
| "Deleting X hours is wasteful" | 保留不可信代码是更大的浪费。 |
| "Keep as reference, write tests first" | 你会偷看参考。删除是必要的。 |
AI不会接受这些合理化。每次你(或AI自己)提出这些理由,技能会引用反驳:
"Too simple to test" → Simple code breaks. Test takes 30 seconds.
Red Flags:自检信号
技能有一个Red Flags列表,让AI自检:
- Code before test
- Test after implementation
- Test passes immediately
- Can't explain why test failed
- Tests added "later"
- Rationalizing "just this once"
- "I already manually tested it"
- "Tests after achieve the same purpose"
- "It's about spirit not ritual"
- "Keep as reference" or "adapt existing code"
- "Already spent X hours, deleting is wasteful"
- "TDD is dogmatic, I'm being pragmatic"
- "This is different because..."
All of these mean: Delete code. Start over with TDD.
如果AI意识到自己在合理化,它会停止,删除已有代码,重新开始TDD流程。
为什么AI能严格执行TDD
关键:AI没有人类的弱点。
人类弱点
- 倾向:想快点完成,测试看起来浪费时间
- 情感:删除已有代码感觉是浪费
- 合理化:"这次可以例外"、"这不适用于简单代码"
AI特点
- 没有时间压力感受:它不觉得测试"浪费时间"
- 没有沉没成本感受:删除代码不感觉"浪费"
- 有明确规则:技能告诉它必须做什么
但AI有另一个弱点:它想帮你。如果技能没有明确禁止,AI可能会迁就你的"跳过测试"请求。
Superpowers的设计是:技能明确禁止所有例外路径。AI看到规则,执行规则。结果是AI成为TDD的严格执行者。
实际观察
在第一个项目的任务2中,我观察到AI执行TDD:
每个函数都经过:
- 写测试
- 运行测试,记录失败原因
- 确认失败原因是"功能缺失"
- 写最小代码
- 运行测试,确认通过
- 自我检查:对照任务要求验证
没有一次跳过。没有一次"先写代码后补测试"。没有一次"这个太简单不需要测试"。
这就是强制执行的效果。
验证清单
Superpowers的TDD技能有一个验证清单,每次任务完成前检查:
- Every new function/method has a test
- Watched each test fail before implementing
- Each test failed for expected reason (feature missing, not typo)
- Wrote minimal code to pass each test
- All tests pass
- Output pristine (no errors, warnings)
- Tests use real code (mocks only if unavoidable)
- Edge cases and errors covered
如果任何一个checkbox不能check,AI知道自己跳过了TDD,必须重来。
结论
Superpowers的TDD不是建议,是强制执行。
核心机制:
- Iron Law:没有生产代码没有失败测试在前
- RED-GREEN-REFACTOR循环,每步验证
- 合理化反驳表,阻止"这次可以例外"
- Red Flags自检,让AI意识到合理化
- 验证清单,完成任务前确认
结果是:AI不迁就你的偷懒倾向,强制执行TDD流程。这不是限制,是保护——保护你免于写出不可信的代码。
下一步
下一篇《调试不再盲目:系统化调试的思维转变》将展示Systematic Debugging技能:
- 四阶段流程:Observe → Hypothesize → Isolate → Fix
- 为什么猜测式调试是时间黑洞
- AI如何帮助你建立证据链