3.1 好测试的四根柱子


3.1 好测试的四根柱子

本节摘要:测试数量上去之后,质量不合格的测试比没有测试更糟——它们随机变红、互相污染、拖慢循环。本节把好测试的标准收敛为四根柱子:快、独立、可复现、自解释,给出每根柱子的检查动作与对治手法。读完你应能给任何一条测试做体检并开出处方。

早期给测试立规矩的人,动机都很朴素:自动化测试刚兴起的年代,团队最深的恐惧不是"没有测试",而是"测试随机失败"——红色出现时你不知道是实现坏了还是测试抽风,几次误报之后没人再信测试,整套资产作废。xUnit 一系的实践者们于是反复提炼"什么样的测试值得信任",从单元测试之父们的口诀到 TODAY、FIRST 等各版缩写,说的其实是同一件事:测试必须像好的测量仪器——量得快、互不干扰、读数稳定、刻度清楚。本节把它收敛成四根柱子。

柱子的样子

图:好测试的四根柱子

图:好测试的四根柱子

四根柱子不是并列的装饰,而是循环的地基:撑着十分钟节拍,独立撑着任意重构的安全网,可复现撑着"红灯即故障"的信任,自解释撑着测试当文档的副业。任何一根塌了,前面辛苦建立的节律都会连锁垮掉。

四根柱子打架时,听谁的

实战里柱子偶尔冲突:为了独立,每个用例重建整套数据,速度就掉了;为了可复现,把网络封进替身,真伪性又打折扣。冲突时的优先级建议是:可复现优先于一切——读数不稳的测试没有信用,信用崩了其他柱子全部白搭;独立次之,它决定测试集能不能并行、能不能红得指名道姓;快排第三,它有预算线(条均百毫秒)但允许个别例外挂慢标记;自解释贯穿全程,与其他柱子几乎不打架。排好优先级,多数"要不要用大夹具"式的争论都有了解答:在守住前两根的前提下尽量快,快不起来的部分隔离出去(5.1 的分层),绝不牺牲前两根换取整体提速。

一条病测试的会诊

对照着看一条灯塔小组真实出现过的测试,四根柱子挨个体检:

# 病例:四柱全塌 user = create_user(" tester ") # 模块级共享状态,还带着没清理的空格 def test_discount(): set_global_promo("SUMMER") # 依赖全局促销位,别的用例会动它 time.sleep(1) # 等缓存过期,硬塞等待 total = checkout(CART_WITH_3_ITEMS) # 名字看不出在验证什么 assert total == 270 # 期望值没有推导过程,魔法数

会诊记录:不独立——全局促销位是公共寄存器,谁后写谁说了算;不可复现——sleep 猜时间,抢不到就红;——每跑一次白等一秒;不自解释——270 从何而来要翻需求文档。同一场景重写成四柱俱全的版本:

def test_member_discount_applies_10_percent_off_300_order(): cart = cart_with(items=[("SKU", Decimal("300.00"))]) pricing = Pricing(promo=fixed_promo("SUMMER", percent=Decimal("0.10")), clock=FakeClock(at="2026-06-01T10:00:00")) assert pricing.member_total(cart) == Decimal("270.00")

注意改动的方式:不是"重写",而是把四根柱子逐一装回去——前提自己构造(独立)、时钟显式注入假对象(可复现)、没有等待(快)、名字与断言里保留推导链(自解释)。后面两节讲的 fixture 与替身,就是把这两种"装柱子"的动作变成批量生产工具。

症状与柱子的对照表

排障时反着用最顺手:先看症状,再查塌了的柱子。

症状 塌了的柱子 第一步处置
单跑绿、全批红 独立 找模块级可变状态,改 fixture 重建
偶尔红、重跑绿 可复现 排查时间、随机、网络、字典顺序
跑批要等半分钟 慢依赖换替身,I/O 型用例隔离
红了要开会解释 自解释 改名、断言带上下文消息
改一处实现红十条 自解释(锁细节) 断言从结构词换成行为词
新人不敢动测试 全体(看不懂的都不敢碰) 先补名字与前提注释,再谈重构

⚠️ 最被低估的是"自解释"。它不影响测试能不能跑,只影响三个月后你能不能看懂——而测试的半衰期恰恰长过实现:实现会重写,测试断言的行为契约往往一直活着。

💡 给"快"立个可执行的预算:单条用例超过一百毫秒就该出示理由,整批超过十秒就该分层——慢的那部分标记出来放到流水线晚段跑(第 6 章),主循环里只留毫秒级用例。

预算贴在显眼处比记在脑子里管用:pytest 配置里加上耗时排行参数(--durations 在 CI 输出的摘要里常驻),超预算的用例在每次流水线日志里自动点名。可视化不改变任何行为,却让"慢"从感觉变成事实——事实才配得上治理动作。

把柱子装进日常

体检不必等测试腐烂再做。灯塔小组后来立了个小规矩:review 测试代码时用四柱当清单,提问固定成四句——它快吗、单跑绿吗、重跑绿吗、红了能看懂吗。四问全过才允许合入。日常写测试时则反过来:先写名字(需求句),再写断言(行为),最后补前提(构造)——顺序对齐了,自解释与独立通常自动到位,剩下快与可复现靠 fixture 和替身这两件工具,正是接下来两节的内容。

四柱还有一层组织价值:它们给了团队讨论测试质量时的共同词汇。以前争论"这条测试写得不好"容易沦为口味之争,现在可以精确到"它塌在可复现上,因为读了系统时钟"——问题一旦被准确命名,解法往往是现成的。共享词汇看似小事,却是第 7 章团队能否落地节律的隐形基础设施。

本节要点回顾

  • 四根柱子:快、独立、可复现、自解释,与 FIRST 口诀同源。
  • 病测试的经典病灶:全局状态、sleep 等待、魔法期望值、锁结构的断言。
  • 处方顺序:先立独立(现场重建),再封可复现(注入不确定源),然后提速,最后打磨可读。
  • review 四问:快吗、单跑绿吗、重跑绿吗、红了能看懂吗。
  • fixture 与替身是批量生产柱子的工具——下一节先讲 fixture。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U