学习路线图
以 Jeff Langr 原书 11 章为准,将学习组织为建立反馈、构造测试、演化复杂系统和团队持续四阶段,并为从零、已有单测、遗留改造和团队落地提供可验收路线。
学习目标
- 能准确定位原书 11 章在“建立反馈、构造测试、演化复杂系统、团队持续”四阶段中的作用与前置关系
- 能根据从零学习、已有单测、遗留改造或团队落地四种目标选择路线,并回补不可跳过的证据基础
- 能用正确红灯、全绿重构、FIRST 审计、特征护栏、并发探针和 CI 健康等可执行产物验收学习,而不是只记录阅读进度
机制总览
学习路线图:机制路径
- 1
这本书教的是一套反馈系统
《Modern C++ Programming with Test-Driven Development》不是 C++ 语法面试题册。它从环境和 Soundex 第一例开始,建立红绿重构纪律;随后讲测试构造、替身、增量设计和质量;再进入遗留、线程、性能与多层证据;最后讨论团队如何长期维持 TDD。
- 2
第一阶段:建立可信红绿循环(Chapter 1-3)
Chapter 1 Global Setup 固定编译器、CMake/CTest、测试框架和依赖身份,并用故意失败证明测试发现与退出码。Chapter 2 A First Example 通过 Soundex 逐条加入首字母、补零、编码、元音、长度与重复规则。Chapter 3 Foundation…
- 3
第二阶段:构造可维护测试与设计(Chapter 4-7)
Chapter 4 Test Construction 组织快慢套件、过滤器、断言、private 边界和参数化;Chapter 5 Test Doubles 区分 fake、stub、spy、mock 并用依赖注入改善设计;Chapter 6 Incremental Design 用简单设计力量和…
章级决策实验
学习路线图:机制与证据
切换《学习路线图》的三个关键教学阶段,先解释机制,再用运行与失败证据验证结论。
选择推理阶段
当前阶段 · 这本书教的是一套反馈系统
《Modern C++ Programming with Test-Driven Development》不是 C++ 语法面试题册。它从环境和 Soundex 第一例开始,建立红绿重构纪律;随后讲测试构造、替身、增量设计和质量;再进入遗留、线程、性能与多层证据;最后讨论团队如何长期维持 TDD。
可核验证据
保存红—绿—重构的最小提交与失败消息,用行为断言、替身交互和重复运行核对「这本书教的是一套反馈系统」是否提供快速反馈。
学完《学习路线图》后,应能从输入和前置条件推导状态变化,并用可重复的构建、运行或边界测试证明结果。
失效—证据矩阵
学习路线图:失效与核验
这本书教的是一套反馈系统
典型失效
若把「这本书教的是一套反馈系统」退化成先写实现再补断言,测试会耦合内部步骤,既不能驱动设计,也无法稳定解释失败。
核验证据
保存红—绿—重构的最小提交与失败消息,用行为断言、替身交互和重复运行核对「这本书教的是一套反馈系统」是否提供快速反馈。
第一阶段:建立可信红绿循环(Chapter 1-3)
典型失效
若把「第一阶段:建立可信红绿循环(Chapter 1-3)」退化成先写实现再补断言,测试会耦合内部步骤,既不能驱动设计,也无法稳定解释失败。
核验证据
保存红—绿—重构的最小提交与失败消息,用行为断言、替身交互和重复运行核对「第一阶段:建立可信红绿循环(Chapter 1-3)」是否提供快速反馈。
第二阶段:构造可维护测试与设计(Chapter 4-7)
典型失效
若把「第二阶段:构造可维护测试与设计(Chapter 4-7)」退化成先写实现再补断言,测试会耦合内部步骤,既不能驱动设计,也无法稳定解释失败。
核验证据
保存红—绿—重构的最小提交与失败消息,用行为断言、替身交互和重复运行核对「第二阶段:构造可维护测试与设计(Chapter 4-7)」是否提供快速反馈。
这本书教的是一套反馈系统
《Modern C++ Programming with Test-Driven Development》不是 C++ 语法面试题册。它从环境和 Soundex 第一例开始,建立红绿重构纪律;随后讲测试构造、替身、增量设计和质量;再进入遗留、线程、性能与多层证据;最后讨论团队如何长期维持 TDD。
↡由失败测试、最小实现、全绿重构和多层自动化证据组成,用来缩短从代码变化到可信结论距离的系统。学习目标不是记住框架宏,而是能面对一个行为回答:下一条最小红灯是什么,依赖怎样控制,失败由哪层定位,结构何时重构,团队怎样确保这些结论进入共享主干。
第一阶段:建立可信红绿循环(Chapter 1-3)
Chapter 1 Global Setup 固定编译器、CMake/CTest、测试框架和依赖身份,并用故意失败证明测试发现与退出码。Chapter 2 A First Example 通过 Soundex 逐条加入首字母、补零、编码、元音、长度与重复规则。Chapter 3 Foundations 把实例抽象为三条 TDD 规则、正确红灯、最小实现、测试清单与成功机制。
↡新测试因目标行为缺失而按预测失败,消息可解释且旧测试此前全绿的状态。阶段出口不是“能写 EXPECT_EQ”,而是从空构建目录完成一次连续记录:确认新测试被发现并正确失败,写最小代码让新旧测试全绿,在不改行为时完成一次重构,并保存命令与结果。
evidence-01: compiler/CMake/framework identity
evidence-02: expected failing test name and diagnostic
evidence-03: minimal production change and full green set
evidence-04: structural refactor with unchanged behavior第二阶段:构造可维护测试与设计(Chapter 4-7)
Chapter 4 Test Construction 组织快慢套件、过滤器、断言、private 边界和参数化;Chapter 5 Test Doubles 区分 fake、stub、spy、mock 并用依赖注入改善设计;Chapter 6 Incremental Design 用简单设计力量和可逆性安排决策;Chapter 7 Quality Tests 用 FIRST 与一个行为焦点审查测试本身。
↡把外部时间、网络、存储等依赖显式化为窄端口,并由组合者传入真实实现或测试替身的设计能力。这一阶段的主线是:测试既要对行为敏感,也要对内部重构稳定。专用断言保留期望与实际,fixture 不隐藏关键输入,参数化压缩稳定规则,mock 只验证业务必要交互,简单设计删除无证据抽象。
TEST(ExpiryReminderTest, SendsNoticeForExpiredOrder) {
FixedClock clock{knownTime()};
RecordingNotifier notifier;
ExpiryReminder reminder{clock, notifier};
reminder.remind(expiredOrder());
EXPECT_THAT(notifier.messages(),
::testing::ElementsAre("Order expired"));
}阶段出口是一份真实测试审计:快层时长与数量、顺序/重复执行结果、一个过度 mock 的修复、一个隐藏依赖的构造注入,以及一次在全绿下完成的责任移动。
第三阶段:在复杂边界保持小步(Chapter 8-10)
Chapter 8 Legacy Challenges 先用特征测试保护未知行为,再建立接缝、加速测试,应用 Mondo Extracto 和 Mikado Method。Chapter 9 TDD and Threading 以 GeoServer/ThreadPool 分层驱动同步行为、队列、生命周期和并发探针。Chapter 10 Additional Concepts 把性能、单元/集成/验收证据、TPP 与 assertions-first 纳入反馈。
↡以固定输入记录遗留代码当前可观察行为,在结构改造时侦测无意语义变化的测试。 ↡用 latch、barrier、状态谓词、不变量和 sanitizer 主动暴露丢任务、竞态、死锁与串行伪装的证据组合。复杂不意味着大步。遗留代码先保护再重构,新行为另写红灯;线程测试先证明同步 oracle,再控制关键交错;性能先定义预算和代表基准;验收失败下沉到最窄单元或集成层复现。
legacy: observe -> characterize -> seam -> new failing behavior
threading: synchronous oracle -> queue contract -> worker lifecycle -> probes
evidence: unit rule -> adapter contract -> acceptance workflow -> benchmark第四阶段:让团队持续(Chapter 11)
Chapter 11 Growing and Sustaining TDD 把个人循环扩展为结对、kata/dojo、覆盖率探针、持续集成、团队标准和社区。核心风险是坏测试死亡螺旋:测试慢脆随机导致少运行,失败失去信任,代码再变得更难测试。
↡每个小变更在一致环境自动构建、运行分层测试并传播失败,让主干保持可交付的共享门禁。阶段出口是一份可运营协议:主干红的 owner 与恢复时限、快层预算、随机测试隔离期限、覆盖率下降后的风险审查、pair/kata 节奏和标准例外流程。指标必须触发动作,不能只放在看板。
11 章不是独立技巧清单
Global Setup 让红绿可信;Test Construction 让失败可读;Test Doubles 让依赖可控;Incremental Design 让结构能持续演化;Legacy 与 Threading 把这些能力带到复杂系统;最后团队机制保护共享反馈。跳章必须知道失去哪项前置证据。
例如直接读线程章却没有正确红灯和快测试分层,很容易写成 sleep 加压力次数;直接做遗留注入却不了解替身角色,会用 mock 锁死内部调用;直接设置覆盖率门槛却没有质量测试观念,会追数字而非行为。
四条可选路线
↡根据当前能力和目标选择章节顺序,同时明确必须回补的前置证据与阶段验收产物。从零系统学按 1 到 11 顺序,每章至少复做一个红绿重构。已有单测从 Foundations、Construction、Doubles 和 Quality 审计现状,再回补环境与第一例。遗留改造先回看 Foundations/Doubles/Quality,再进入 Chapter 8。团队落地可以从 Chapter 11 健康检查开始,但实际修复通常要回到 Chapter 4、7、8。
路线可以跳读,能力不能凭空跳过。若当前没有一键可信入口,先回 Chapter 1;若测试随机且绑定实现,先回 Chapter 4-7;若大改无护栏,回 Chapter 8;若线程测试靠 sleep,回 Chapter 9 的受控同步。
每章使用同一学习闭环
↡对章节先预测、操作复现、解释证据、迁移到真实代码并复查遗漏的五步学习方法。- 先预测:写下测试应怎样失败、哪项工具或边界负责
- 操作复现:运行最小示例,保存命令、用例数、失败差值和退出码
- 解释证据:说明为何不是环境、旧产物或偶然调度
- 迁移实践:在自己的模块应用一个窄改造,不照抄玩具结构
- 复查遗漏:列边界、替身风险、慢层和团队门禁缺口
只阅读答案无法形成判断。每章的交互图、代码和练习应在真实工程或独立 kata 中重做,并把“我知道”换成可重复的运行证据。
全书验收项目
完成 11 章后,选择一个含外部依赖和至少一个并发或遗留边界的小服务,交付:
- 固定工具链与一键测试入口,故意失败能传播到 CI
- 由验收例下沉的快速领域测试与真实适配器契约
- 至少一个手写替身和一个经理由明确的 mock/fake 选择
- 一次有特征护栏的遗留提取或一次受控并发交错测试
- 性能基线与预算,不在普通单元测试写抖动阈值
- 团队标准草案,含红主干 owner、随机测试期限和快层预算
验收看证据链,不看总测试数。一个项目能明确回答“什么行为、哪层证明、失败如何定位、结构为何这样、团队怎样持续”,才说明路线完成。
第一步:按四阶段建立能力出口
从可信红绿循环开始,进入测试构造与设计,再处理遗留/并发/性能,最后建立团队门禁;每阶段用实际产物验收。
小结
- 全书 11 章形成从个人红绿循环到团队持续反馈的完整系统,不是 C++ 面试题集合
- Chapter 1-3 建立可信环境、Soundex 小步与 TDD 基础;Chapter 4-7 建立测试构造、替身、设计与质量
- Chapter 8-10 把小步带入遗留、并发、性能和多层证据;Chapter 11 建立长期团队机制
- 四条路线允许按目标跳读,但必须回补正确红灯、快测试、可控依赖和行为护栏等前置能力
- 每章用先预测、复现、解释、迁移、复查闭环学习,最终以一个真实项目证据链验收
练习
- 问题 1:章节定位。 现有测试大量使用真实时钟和网络,失败慢且随机,应优先回看哪些章节,产出什么?
- 问题 2:遗留路线。 团队要改一个无测试的全局日志处理器,为什么不能只读 Chapter 8?
- 问题 3:团队验收。 团队设置了覆盖率 90%,但主干随机红、没人负责。为什么路线尚未完成?
名词解释
名词解释
本章出现的专业名词,用大白话再讲一遍。
- TDD 反馈系统
- 由失败测试、最小实现、重构和多层证据组成的短反馈系统。
- 正确红灯
- 因目标行为缺失而按预测失败且消息可解释的测试状态。
- 可控依赖
- 以窄端口显式注入真实实现或测试替身的能力。
- 特征护栏
- 记录遗留当前行为并保护结构改造的测试。
- 并发探针
- 以事件、不变量、重复和 sanitizer 暴露并发缺陷的证据组合。
- 持续集成门禁
- 自动构建测试并传播失败、保护共享主干的系统。
- 目标路线
- 按当前目标选章并明确回补能力和验收产物的路径。
- 章节学习闭环
- 先预测、复现、解释、迁移和复查的五步学习方法。