来源:Kent Beck "Test Driven Development by Example" + Martin Fowler "Refactoring" 提炼时间:2026-04-24
TDD 不是"先写测试再写代码"。这个理解太浅,会导致实践变形。
TDD 是一种设计工作流——用测试来驱动接口设计,用快速反馈来驱动代码演进。
好的测试:
// ✅ 描述行为
test('用户可以用书名搜索绘本', async () => {
const results = await searchBooks('丢失的星星');
expect(results).toContainEqual(expect.objectContaining({ title: '丢失的星星' }));
});
坏的测试:
// ❌ 描述实现
test('searchBooks 调用了 Prisma 的 where 参数', () => {
const mock = prismaMock.book.findMany.mockResolvedTo([]);
await searchBooks('test');
expect(prismaMock.book.findMany).toHaveBeenCalledWith({
where: expect.objectContaining({ title: { contains: 'test' } })
});
});
为什么重要:实现可以随时改,测试不应该因为内部重构而失败。测试描述"能做什么",不是"怎么做"。
❌ 横向切片(错误方式):
RED: 写 test1, test2, test3, test4, test5
GREEN: 一次性写 impl1, impl2, impl3, impl4, impl5
✅ 垂直切片(正确方式):
RED→GREEN: test1 → impl1
RED→GREEN: test2 → impl2
RED→GREEN: test3 → impl3
横向切片的问题: - 一次写所有测试,测试的是"想象的行为"而不是"实际的需求" - 测的是数据结构形状,不是用户价值 - 需求变时,测试全部要改
垂直切片的价值: - 每个测试都基于上一个测试学会的信息 - 每个测试都是对"这条 user story 是否完成"的验证 - 需求变时,只改相关的测试
[RED] 写一个不通过的测试 → 确认哪里不对
[GREEN] 用最小代码让它通过 → 不求完美,只求通过
[REFACTOR] 在测试保护下改善代码 → 安全地改结构
关键规则: - 不跳过任何阶段 - RED 阶段不写任何实现代码 - GREEN 阶段不追求完美,只求测试通过 - REFACTOR 阶段在测试保护下大胆重构 - 永远不让系统处于 RED 状态过夜
满足以下任一条件的测试是行为测试:
AI 生成代码的问题:看起来对,实际可能不对。传统编程里,看一眼知道对不对;AI 生成时,每行看起来都对,要跑才知道。
TDD 提供了快速验证回路——AI 生成代码 → 测试立刻告诉你哪里不对 → AI 修正 → 再测。
没有测试,AI 代码的错误可能藏了很久才发现。
用 AI 辅助 TDD: 1. 让 AI 先写测试(描述你想验证的行为) 2. 你 review 测试是否合理 3. 让 AI 基于测试写实现 4. 测试通过后,让 AI 提出重构机会
关键:不要让 AI 同时写测试和实现——这样 AI 会走捷径(测试mock一切让实现轻松通过)。
拿到一个测试,问自己:
参考:Kent Beck "Test Driven Development by Example", 2002 参考:Martin Fowler "Refactoring", 2018