Skip to content

测试作为设计工具 = 先写测试就是先想清楚 API ​

解决什么问题:测试沦为验证工具,难以推行—— 测试的真正价值是设计工具。先写测试 = 先想清楚 API。

业务问题 ​

真实场景 ​

场景 1:测试 = 验证工具的反模式

团队反模式:
  - 先写代码
  - 再补测试("为了让 CI 绿")
  - 测试是负担
  - 测试覆盖低
  - 重构恐惧
  
结果:
  - 测试质量差(只是"运行通过")
  - 不敢重构(测试脆弱)
  - bug 多

场景 2:测试 = 设计工具的正模式

团队正模式:
  - 先写测试(TDD)
  - 测试 = API 设计的"第一次调用"
  - 测试 = 文档(可执行)
  - 测试 = 重构保障
  
结果:
  - API 易用(测试就是 caller)
  - 重构有信心
  - bug 少

失败模式 ​

失败模式后果
后补测试测试脆弱、只是"运行通过"
测试实现重构就坏
Mock 一切测试与生产脱节
大测试覆盖广慢、脆弱、难调试

控制论视角 ​

Ch 4 §4.6:"控制律的可验证性" + Ch 6 §6.7:"可重复性"

测试 = Ch 4 §4.6 可验证性
  - 控制律(代码)必须可被验证
  - 测试 = 验证的具体形式
  - 测试先行 = 设计阶段的验证
  
测试 = Ch 6 §6.7 可重复性
  - 控制律输出必须可重复
  - 测试 = 可重复的具体形式

核心概念 ​

测试的 4 个价值(按重要性) ​

1. 设计工具(最重要)
   - 先写测试 = 强迫设计 API
   - 测试 = API 的第一次 caller
   - 好的测试 = 好的设计

2. 文档(可执行)
   - 测试 = 用代码写的"如何使用"
   - 比注释更可靠(不会过期)

3. 重构保护
   - 改代码 → 测试保证不破坏
   - 改设计 → 测试保证行为不变

4. 抓 bug(最少价值)
   - 测试覆盖率 ≠ 无 bug
   - 但显著减少 bug

Google 的 Small/Medium/Large ​

Small Tests:
  - 单一进程
  - 无网络 / 文件系统
  - 无 sleep
  - < 100ms
  
Medium Tests:
  - 单机
  - localhost 网络可用
  - < 1s
  
Large Tests:
  - 多机
  - 真实集成
  - 秒级以上

测试金字塔(Google 版) ​

   / E2E \         ← 10%:关键路径
  / 集成  \        ← 20%:服务间协作
 / Small   \       ← 70%:单元 + 小集成

工程实践 ​

决策 1:测试覆盖率目标 ​

不追求 100%(不可能也不必要)
追求 80%+(关键路径全覆盖)

"关键路径"定义:
  - 业务核心逻辑
  - 公开 API
  - 数据持久化
  - 安全相关

决策 2:测试 = 文档策略 ​

原则:
  - 测试名 = 文档标题
  - 测试结构 = AAA(Arrange-Act-Assert)
  - 测试名 = 业务语言(不是技术语言)
  
例(反模式):
  def test_order_creation_with_valid_input():
      # 业务名 = 技术名 ✓ 但不够具体
      
例(正模式):
  def test_creating_an_order_with_out_of_stock_item_fails():
      # 业务名 = 完整场景 ✓

实战 1:测试驱动设计的 4 步 ​

Step 1:写失败的测试(Red)
  - 测试调用还不存在的 API
  - 强迫想清楚:API 长什么样?
  
Step 2:让测试通过(Green)
  - 写最简单的实现
  - 不追求优雅
  
Step 3:重构(Refactor)
  - 优化设计
  - 测试保护下重构
  
Step 4:扩展(Repeat)
  - 下一个场景

反模式 vs 正模式 ​

反模式正模式
后补测试TDD / 测试先行
测试实现细节测试行为
Mock 一切用真实对象(必要时 mock)
大测试覆盖广小测试覆盖广
100% 覆盖80%+ 关键路径

性能指标 ​

指标衡量健康值
测试覆盖率关键路径覆盖率> 80%
测试大小比例Small : Medium : Large70 : 20 : 10
测试运行时间全套测试时间< 10min
测试稳定性flaky 率< 1%

边界判断 ​

何时用 TDD ​

  • 业务核心
  • 公开 API
  • 复杂逻辑
  • 易出 bug 的地方

何时不用 TDD ​

  • 一次性脚本
  • 实验代码
  • UI 原型
  • 简单的 CRUD

何时升级 ​

当前升级到触发条件
后补测试测试先行设计质量差
大量大测试测试金字塔跑得慢
测试实现测试行为重构频繁

关键洞察 ​

  1. 测试 = 设计工具——最大价值是先想清楚 API。
  2. 小测试 = 大信心——70% small 是 Google 数据支撑。
  3. 测试是文档——可执行、永不过期。
  4. TDD 不仅是方法——它是设计的纪律。
  5. 与 cybernetics 同构——Ch 4 §4.6 可验证 = 测试 = 控制律的验证机制。

从名家方法论与工程化思路中蒸馏出自己的工程体系。