一、TDD入门:什么是TDD、TDD的三大原则(红-绿-重构)、TDD与传统开发模式对比、TDD的优势与挑战
好,咱们直接进入正题。
TDD,全称 Test-Driven Development,中文叫测试驱动开发。说白了,就是先写测试,再写代码。这个顺序,跟大多数人习惯的“先写代码,再测试”正好反过来。
我第一次接触TDD时,心里也犯嘀咕:代码都没写,测什么呢?这不是本末倒置吗?后来真正用起来才发现,嗯,这玩意儿确实有点东西。
1.1 什么是TDD?
TDD不是一种测试技术,而是一种设计技术。它的核心思想是:通过测试来驱动代码的设计和实现。
具体流程是这样的:
- 先写一个会失败的测试(红)
- 写刚好能让测试通过的代码(绿)
- 重构代码,让它变得更好(重构)
循环往复,直到功能完成。
核心要点:TDD关注的是“代码应该做什么”,而不是“代码怎么实现”。
我个人的习惯是,拿到一个需求后,先不急着写代码。我会先问自己:这个功能最终要输出什么?边界情况有哪些?异常怎么处理?想清楚这些,再开始写测试。
1.2 TDD的三大原则:红-绿-重构
这三个词,是TDD的灵魂。咱们一个一个说。
原则一:红(Red)
先写一个会失败的测试。为什么?因为你要证明你的测试是有效的。如果一个测试一开始就通过了,那它可能什么都没测到。
举个例子,假设我们要写一个加法函数:
// 第一步:写测试
const { add } = require('./calculator');
test('adds 1 + 2 to equal 3', () => {
expect(add(1, 2)).toBe(3);
});
这时候运行测试,肯定会报错——因为 add 函数还不存在。这就是“红”。
小技巧:红阶段不要写太多测试。一次只写一个,聚焦在最小的功能点上。
原则二:绿(Green)
写刚好能让测试通过的代码。注意,是“刚好”,不是“完美”。
// 第二步:写实现
function add(a, b) {
return a + b;
}
module.exports = { add };
运行测试,通过。这就是“绿”。
我曾经见过有人在这个阶段就开始优化代码,加各种边界判断。其实没必要。先让测试通过,后面有的是时间重构。
原则三:重构(Refactor)
测试通过了,代码能跑了。但代码写得怎么样?有没有重复?有没有可以优化的地方?这时候就可以放心大胆地重构了。
为什么?因为你有测试兜底。改错了,测试会告诉你。
// 第三步:重构(假设后续需要支持更多功能)
function add(...args) {
return args.reduce((sum, current) => sum + current, 0);
}
重构完,再跑一遍测试。绿,说明没问题。
注意:重构阶段不要新增功能。只改结构,不改行为。新增功能请回到“红”阶段。
1.3 TDD与传统开发模式对比
咱们来做个对比,看看TDD和传统模式到底差在哪。
| 对比维度 | 传统开发模式 | TDD模式 |
|---|---|---|
| 开发顺序 | 先写代码,后写测试 | 先写测试,后写代码 |
| 测试覆盖率 | 容易遗漏,补测试像交作业 | 天然高覆盖率,每个功能都有测试 |
| 代码设计 | 容易过度设计或设计不足 | 测试驱动设计,刚好够用 |
| 调试时间 | 后期集中调试,耗时巨大 | 边写边测,问题早发现 |
| 重构信心 | 不敢改,怕改出问题 | 有测试兜底,放心改 |
| 文档价值 | 测试用例常被忽略 | 测试即文档,可读性强 |
你看,差别还是挺明显的。传统模式像是“先盖楼再验收”,TDD则是“边设计边验收”。哪个更靠谱?你想想看。
1.4 TDD的优势与挑战
任何方法论都有两面性。TDD也不是银弹。
优势
- 代码质量高:每个功能都有测试覆盖,bug率明显下降。我在一个项目中实践TDD后,线上bug减少了大概60%。
- 设计更清晰:写测试倒逼你思考接口设计。如果测试很难写,说明你的代码设计有问题。
- 重构更安全:这个前面说过了,有测试兜底,改代码不心虚。
- 文档即代码:测试用例就是最好的使用文档。新同事看测试,比看文档快多了。
挑战
- 学习曲线陡:刚开始会很不习惯。我刚开始用TDD时,前两周效率反而下降了。这是正常的,熬过去就好。
- 初期速度慢:写测试确实需要时间。但你要算总账——后期调试时间省下来了。
- 不适合所有场景:UI界面、复杂集成测试,TDD用起来会比较吃力。这时候可以结合其他测试策略。
- 团队共识:如果团队只有你一个人用TDD,效果会大打折扣。需要大家一起配合。
我的建议:不要一开始就追求100% TDD。先从核心业务逻辑开始,慢慢扩大范围。我曾经在一个项目中,只对核心模块用了TDD,效果已经非常好了。
好了,第一章就到这里。记住三个关键词:红、绿、重构。这是TDD的基石,后面的所有内容都建立在这三个原则之上。
下一章,咱们会实际搭建一个Node.js项目,开始写第一个TDD测试。准备好了吗?