📄 本篇摘要
TDD(测试驱动开发)=把顺序反过来:先写测试,再写实现。三拍子循环:红(写一个失败的测试)→ 绿(用最少的代码让它通过)→ 重构(整理干净,测试保持绿)。它是 5-11 重构的安全感来源,也是 XP 的核心实践。
📝 关系
上一节:重构 | 下一节:E-R 图与 DFD 图
一、顺序反过来的魔法
传统流程:写代码 → 写测试(有心情的话)。TDD 把测试提到最前:
- 红:写一个小测试,描述下一个要有的行为——此时必失败(功能还没有);
- 绿:写刚好让它通过的实现——不求完美,求通过;
- 重构:测试保护下整理代码——改名、拆函数、消重复。
然后回到 1,循环往复。每个循环几分钟到半小时,测试集像滚雪球一样长大。
二、为什么反过来就有效
- 测试先行倒逼设计:写测试时你必须先想清楚【这个函数怎么被调用、返回什么】——接口先于实现。难写的测试立刻暴露难用的设计(趁早改,比写完再改便宜)。
- 永远有安全网:任何时候改代码,全套测试一键验证(5-11 重构因此才敢做)。
- 进度可见:红转绿的瞬间就是进度——没有【写了一半不知道到哪了】的迷雾。
测试优先是 TDD 的同义词(强调测试在实现之前);XP(极限编程,Extreme Programming)是 Kent Beck 提出的敏捷方法论,TDD 是它十二个实践里最出名的一个,同门还有结对编程、持续集成(5-10)、小步发布。
三、TDD 的账本
教材提醒两点平衡:
- 不是所有代码都值得 TDD:探索性的草稿代码、一次性脚本可以直接写;业务逻辑——规则多、边界多、易变——是 TDD 的主场。
- 测试也是代码:也要 5-2 的命名、5-11 的重构——烂测试比没测试更误导人。
四、动手 Demo:完整走一遍红-绿-重构
# ===== 第 1 轮·红:描述最简单的需求 =====
def test_fizz_1():
assert fizz(1) == "1"
# 此刻 fizz 不存在 -> 测试失败(红)
# ===== 第 1 轮·绿:最少的实现 =====
def fizz(n):
return str(n)
# 通过(绿)——别嫌它简陋,【刚好通过】就是 TDD 的节奏
# ===== 第 2 轮·红:3 的倍数 =====
assert fizz(3) == "Fizz" # 失败(当前返回 "3")
# ===== 第 2 轮·绿 =====
def fizz(n):
return "Fizz" if n % 3 == 0 else str(n)
# ===== 第 3 轮·红:5 的倍数,再绿 =====
assert fizz(5) == "Buzz"
def fizz(n):
if n % 15 == 0:
return "FizzBuzz"
if n % 3 == 0:
return "Fizz"
if n % 5 == 0:
return "Buzz"
return str(n)
# ===== 重构:命名与结构已清晰,测试全绿 =====
for n in [1, 3, 5, 15, 7, 30]:
print(n, "->", fizz(n))
沙箱实跑输出:
1 -> 1
3 -> Fizz
5 -> Buzz
15 -> FizzBuzz
7 -> 7
30 -> FizzBuzz
看到什么算成功:六个输入全部符合 FizzBuzz 规则(3/5/15 的倍数各自正确)。
读结果:经典 FizzBuzz 题目被拆成三轮红绿——每一轮只增加一条规则,规则间的相互作用(15=3×5)在测试保护下自然浮现。注意顺序:先处理 15 再处理 3/5,条件顺序错了 15 会输出 Fizz——这正是边值思维(5-6)在 TDD 里落地。
五、30 秒实验
把 n % 15 == 0 那个分支挪到最后,重跑 fizz(15)——输出 Fizz 而不是 FizzBuzz,立刻红。TDD 下你永远不会带着这个 bug 走很远:它当场暴露。
六、常见误区
| 误区 | 真相 |
|---|---|
| 先写完实现再补测试=一样 | 补的测试倾向【顺着实现写】;先写的测试倒逼【从使用者视角设计】 |
| TDD 拖慢进度 | 前期慢、后期赚:调试时间锐减,重构不再心惊 |
| 测试写完就不用维护 | 测试也是代码,命名与重构一样待遇(本节第三节) |
自测三问(点击展开)
1. **红-绿-重构各做什么?** 答:红=写失败的新测试;绿=用最少实现让它通过;重构=保持绿的前提下整理。 2. **测试先行为什么能改善设计?** 答:写测试必须先从调用者视角定接口,难用的设计当场暴露。 3. **TDD 的主场是哪类代码?** 答:规则多、边界多、易变的业务逻辑;草稿脚本不必强上。- ☐ 5-12 学习完成
相关笔记
- 重构 —— 三拍子的第三拍
- 等价划分与边值分析 —— 条件顺序的边值思维
- ⌨️ 编程原理 · 索引 —— 全课路线图