4.4 敏捷下的单元测试

从功能完成后由人手工点一遍走到每次小变更立即得到可定位反馈,沿单元测试隔离、断言、清理和回归边界诊断测试不稳定。

学习目标

  • 能沿安排夹具、执行单元、断言结果、清理状态和回归重放追踪一次隔离单元测试
  • 能解释敏捷反馈为何依赖快速、确定、可重复的测试,以及时间、网络和共享状态如何破坏确定性
  • 能在正常、边界和故障场景中回答:测试随机红绿时,哪一个外部依赖必须被替换或隔离

为什么需要这一机制

本页依据刘欣《码农翻身》(2018 年第 1 版)及出版社公开书目信息,独立重构 4.4 敏捷下的单元测试。正文、代码、图示、实验和练习都是本课程重新设计的教学材料,不复制原书正文、插图、练习答案或代码。

4.4 敏捷下的单元测试 不能停在“多写几个测试”。真实系统要解决的变化是从 功能完成后由人手工点一遍每次小变更立即得到可定位反馈;可执行机制是:单元测试在隔离边界内安排输入、执行行为并断言结果,敏捷迭代依赖快速、确定、可重复的反馈而非测试数量。

单元测试链:隔离输入,给小变更确定反馈Arrange、Act、Assert 之后仍要清理并重放,避免反馈被状态污染1安排夹具输入 + 替身输入证据2执行单元一个行为反馈边界3断言结果结果 + 交互稳定性证据4清理状态归零 + 关闭稳定性证据5回归重放稳定反馈稳定性证据真实时间、网络或共享状态进入单元边界时,反馈就不再确定
专属图示:把五个官方目录标签映射到可重放的单元测试生命周期。

三个会让单元测试失真的陷阱

五个目录节点到测试证据

4.4 敏捷下的单元测试

中,最小合同是

test=arrange+act+asserttest=arrange+act+assert

但完整的可重放测试还需要清理和回归重放。测试数量不等于反馈质量;确定性、隔离边界和失败定位才决定它能否支持敏捷迭代。

敏捷运动

中,测试的价值是缩短反馈回路。快不只是执行时间短,还要能在相同输入下给出相同判定,并把失败指向一个小范围变更。

困惑

中,先检查测试是否把网络、时钟、共享数据库或环境状态当成隐藏输入。覆盖率高仍可能缺少隔离和可诊断断言。

讨论

中,把单元测试、集成测试和端到端测试按风险分层。不是所有外部依赖都要伪造,但每种测试都应有清晰速度、范围和失败归因。

一年以后

中,测试要能抵抗时间推移:固定时钟、版本化夹具、清理共享状态,定期删除只测实现细节的脆弱断言。

单元测试链:隔离输入,给小变更确定反馈Arrange、Act、Assert 之后仍要清理并重放,避免反馈被状态污染1安排夹具输入 + 替身输入证据2执行单元一个行为反馈边界3断言结果结果 + 交互稳定性证据4清理状态归零 + 关闭稳定性证据5回归重放稳定反馈稳定性证据真实时间、网络或共享状态进入单元边界时,反馈就不再确定
专属图示:把五个官方目录标签映射到可重放的单元测试生命周期。

最小可重放实现

fixture = arrange(clock=fixed, network=fake, state=fresh)
actual = act(fixture, input)
assert actual == expected
cleanup(fixture)
assert replay_same_case() == expected

这段实现草图只表达单元测试合同,不复制原书叙事或代码。实际运行时应保存夹具、替身、输入、断言、调用记录、清理结果和回归轨迹,使另一位读者能够从干净状态重放。

五步复核一次单元测试

分步1 / 5

1. 安排隔离夹具

固定时钟、输入、替身、依赖边界和初始状态。先预测正常案例的结果和交互,再运行;不可控依赖要被显式记录,而不是藏在全局环境里。

单元测试链:隔离输入,给小变更确定反馈Arrange、Act、Assert 之后仍要清理并重放,避免反馈被状态污染1安排夹具输入 + 替身输入证据2执行单元一个行为反馈边界3断言结果结果 + 交互稳定性证据4清理状态归零 + 关闭稳定性证据5回归重放稳定反馈稳定性证据真实时间、网络或共享状态进入单元边界时,反馈就不再确定
专属图示:把五个官方目录标签映射到可重放的单元测试生命周期。

Lab

单元测试确定性与清理实验

先预测测试边界会影响哪条证据,再切换正常、边界和隐藏依赖样本并重置。

固定时钟和替身,夹具独立,结果与交互稳定

arrange=fresh → act=unit → assert=result+calls → cleanup=zero → replay=match

判定

accept:快速、确定、可重放

当前样本:确定反馈;保存夹具、时钟、替身、输入、断言、调用记录、环境和清理轨迹。

正常、边界与故障证据矩阵

单元测试证据矩阵:绿色必须能被稳定重放正常样本看隔离,边界样本看合同,故障样本看隐藏依赖观察项正常边界故障夹具状态新鲜输入变化共享泄露执行单元隔离错误响应网络进入断言结果明确边界覆盖断言过弱回归重复一致版本变化随机红绿先记录环境与首个差异,再判断测试是否真的确定
专属图示:让敏捷反馈、测试边界、长期回归和故障诊断共享同一证据表。
样本只改变的变量预期判定必存证据
正常夹具、输入、替身和状态均固定结果与交互稳定,清理完成夹具、断言、调用记录、耗时
边界输入、时间、错误响应或状态改变断言明确,失败可定位样本、预期、实际、首差异
故障真实时间、网络或共享数据库进入标记不确定性并隔离或升级测试层外部依赖、随机种子、环境、复位

故障诊断:先分开隔离、断言与清理

  1. 夹具侧:查时钟、输入、替身、状态和依赖边界;相同代码随机红绿通常有隐藏输入。
  2. 执行侧:查被测单元是否越界访问网络、文件、时间或共享数据库;把集成责任误塞进单元测试会放大噪声。
  3. 断言侧:查返回、异常、调用、顺序和副作用;“没有抛异常”不是完整结果。
  4. 清理侧:查全局、数据库、文件、mock 记录和线程是否归零;顺序敏感常说明状态泄露。

如果测试随机失败,先固定时钟和随机种子,再隔离网络与共享状态;如果测试全绿但用户行为错误,补强断言和边界;如果运行越来越慢,按风险把外部依赖移到集成层。每次只改变一个依赖,并重放可信基线。

术语表

名词解释

本章出现的专业名词,用大白话再讲一遍。

4.4 敏捷下的单元测试

在隔离边界内安排、执行、断言和清理,为小变更提供快速确定反馈的机制。

敏捷运动

以小增量和紧邻自动反馈缩短发现、定位和修复成本的开发节奏。

困惑

测试看似绿色或覆盖充分,却无法解释随机失败与真实行为的诊断状态。

讨论

按边界、替身、断言和成本比较单元、集成与端到端测试的分析阶段。

一年以后

回归套件仍能稳定重放历史行为,并在接口变化时暴露真实契约差异的长期状态。

练习

练习

问题 1(4.4 敏捷下的单元测试、敏捷运动): 为什么敏捷团队需要快速、确定的单元反馈,而不是只在功能完成后手工点一遍?

问题 2(困惑、讨论): 测试依赖真实网络时随机红绿,应该直接重试,还是先改变测试边界?

问题 3(一年以后): 如何判断一年后的回归测试仍然保护真实合同,而不是只保护实现细节?

资料与写作方式声明

本章以码农翻身权威目录界定学习范围,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

本页小结

4.4 敏捷下的单元测试 的关键不是测试数量,而是隔离、确定、强断言、清理和可重放反馈。完成标准是把五个目录概念落到同一条测试证据链,定位真实时间、网络或共享状态造成的首个偏离,并证明复位后的回归仍可稳定运行。

讨论

评论区加载中…