TDD
测试驱动开发
先写测试。看它失败。写让它通过的最简代码。重构。重复。
最近审阅:
审阅人Kevin Riedl
wiki ↗
TDD 是一种纪律,不是方法论。循环是:红(写一个会失败的测试)、绿(写让它通过的最简代码)、Refactor(在不破坏测试的前提下清理)。照字面做,它产出高测试覆盖率的代码,以及一种对抗过度工程的强制力。这种纪律只有在那些测试每次变更都跑时才会有回报,所以 TDD 和 CI/CD 是兄弟,不是分开的两件事。
多数团队嘴上做 TDD、实际却不做的原因:当下先写测试感觉更慢。复利的回报(Refactor 安全、回归覆盖、朝更小单元的设计压力)要数月之后才显现。到那时,团队早已停止先写测试,并说服自己它从没起过作用。
TDD 在哪里赚回成本、在哪里只是表演,举个实际例子:一个支付对账模块有棘手的边缘情况(部分退款、货币舍入、重试)。先写那个会失败的测试,迫使你在代码存在之前就陈述期望行为,而当六个月后有人「简化」舍入时,那套套件抓住了回归。那是 TDD 在为自己买单。再对照一个你两周后就要删掉的一次性数据导入脚本:在那里先写测试纯属开销。诚实的规则是对逻辑密集、出错代价高的代码做 TDD,其余的不做。
最常见的错误是把覆盖率当成一个目标。追 90%,团队就会为 Getter 和 Setter 写测试去凑那个数字,却跳过真正 Bug 所在的集成测试。覆盖率是一个有用的诊断、一个糟糕的目标;它是个会被刷分的指标。Wavect 在它有回报的地方用 TDD:任何和钱相关的东西做集成测试,任何面向客户的东西做契约测试,产品需要读得懂的地方做 BDD 式验收测试,不平凡的逻辑做单元测试。我们把难的部分测好,而不是把所有部分平均地测,并且把它当作一个健康的 Agile 循环里的一项实践,而不是一个要打的勾。
// FAQ