功能测试流程与自动化脚本
8.8 TDD工作流详解
Tip
先画靶子再射箭,每一箭都中十环。
1. 为什么要学这个?
大多数人的开发习惯是:
- 写代码 (凭感觉写)
- 手动测 (点点点)
- 发现 Bug (修修改改)
- 补单元测试 (为了应付 KPI) -> 这是最痛苦的,因为你已经不想看那堆烂代码了。
TDD (测试驱动开发) 强迫你把顺序反过来:先把目标定死 (靶子),再去写实现 (射箭)。 这样写出来的代码,天然就是可测的、解耦的,而且你永远确信它是对的。
2. 核心概念:红 -> 绿 -> 重构 (Red-Green-Refactor)
TDD 的节奏就像红绿灯,永远只有三步:
- 🔴 Red (红灯):先写一个一定会失败的测试。
- 心里想:“我要实现一个
isLeapYear(year)函数”。 - 写测试:
expect(isLeapYear(2000)).toBe(true)。 - 运行:报错!(因为函数还不存在)。这一步证明了你的测试是有效的。
- 心里想:“我要实现一个
- 🟢 Green (绿灯):写最简单的代码让它通过。
- 写实现:
export const isLeapYear = (y) => y % 400 === 0。 - 运行:通过!
- 写实现:
- 🔵 Refactor (重构):优化代码。
- 优化:整理逻辑,处理边缘情况,但必须保证测试一直是绿的。
3. 在 AI 时代,TDD 变了
以前 TDD 难推行,是因为写测试代码很累。 现在,TDD 是与 AI 结对编程的最佳姿势:
- Prompt: "帮我生成
isValidEmail函数的 10 个测试用例,覆盖各种奇葩的非法邮箱。" - User: 审查这些用例 (靶子立好了)。
- Prompt: "现在写出实现代码,让这些测试变绿。"
- AI: 生成代码。
- User: 运行测试。全绿?收工。
不仅快,而且比你自己手写的逻辑更严密。
4. 真实案例
Story
微软 Zune 播放器的“闰年死机” (2008年12月31日)
2008 年的最后一天,全球数百万台微软 Zune 播放器突然集体死机。 原因:一段处理日期的代码出现了死循环。
while (days > 365) {
if (isLeapYear(year)) {
if (days > 366) { ... }
// 💀 如果恰好是闰年的最后一天 (days == 366),这里什么都不做,无限循环!
}
}
如果用了 TDD:
只要开发人员在写这行代码前,先写这一行测试:
expect(convertDaysToYear(366, 2008)).toBe('2009-01-01')
他就会在敲下代码的第 1 分钟发现死循环 (Red),而不是等到全球几百万人同时开机的那一刻。
5. 本章小结
- 倒着做:先写测试,再写代码。
- 红绿灯:Red (失败) -> Green (通过) -> Refactor (优化)。
- 拥抱 AI:让 AI 帮你立靶子 (写测试),你去负责射箭 (Review)。