第1章:覆盖率驱动方法论——TDD与CDD的区别

大家好,我是你们的老朋友。今天咱们聊聊测试驱动开发(TDD)和覆盖率驱动开发(CDD)的区别。这两个概念,我见过太多人搞混了。

先说说我的经历。几年前我带一个嵌入式项目,团队严格执行TDD。代码写得很漂亮,测试用例也很多。但上线前做覆盖率分析,发现核心模块的覆盖率只有60%。大家傻眼了——测试都通过了啊,怎么覆盖率这么低?

这就是TDD的盲区。你写了测试,但测了什么?测了多少?没人知道。说白了,TDD关注的是「测试先行」,而CDD关注的是「测全了没」。

1.1 TDD:先写测试,再写代码

TDD的核心流程,大家应该都熟悉:

  1. 写一个失败的测试用例
  2. 写刚好能让测试通过的代码
  3. 重构代码

这个循环很漂亮。但有个问题——你怎么知道测试用例覆盖了所有场景?

TDD的致命伤:测试通过 ≠ 代码没问题。你只是验证了你想到的场景,没想到的呢?

我记得有一次,团队用TDD开发一个状态机。测试全过了,但上线后有个边界条件没覆盖到,导致系统崩溃。事后分析,那个场景其实很简单,就是没人想到要测它。

1.2 CDD:覆盖率说了算

CDD的思路完全不同。它把覆盖率作为测试的「第一性原理」。流程是这样的:

  1. 先写代码(或者先有设计)
  2. 分析代码的覆盖率目标(比如行覆盖90%,分支覆盖85%)
  3. 写测试用例,目标是达到覆盖率目标
  4. 运行测试,分析覆盖率报告
  5. 补充测试,直到达标

你想想看,TDD是「先写测试再写代码」,CDD是「先定覆盖率目标再写测试」。方向完全不同。

我的建议:不要非此即彼。我习惯的做法是:核心逻辑用TDD保证正确性,然后用CDD保证完整性。两者互补,效果最好。

1.3 核心区别对比

咱们用一张表说清楚:

维度 TDD CDD
驱动方式 测试用例驱动 覆盖率数据驱动
关注点 代码行为是否正确 代码是否被充分测试
测试时机 先写测试,后写代码 先定目标,后补测试
质量保证 依赖测试设计能力 依赖覆盖率分析工具
适用场景 新功能开发、算法实现 回归测试、安全关键系统
常见误区 测试通过就以为够了 盲目追求100%覆盖率

嗯,这里要注意。TDD和CDD不是对立的。我见过最好的团队,是把两者结合起来用。比如:

  • 新功能用TDD开发,保证每个功能点都有测试
  • 上线前用CDD做一轮覆盖率分析,查漏补缺
  • 持续集成中同时跑TDD的单元测试和CDD的覆盖率检查

1.4 覆盖率驱动测试的核心流程

CDD的核心流程,我总结为四步:

  1. 定目标:根据项目风险等级,设定覆盖率目标。比如核心模块行覆盖≥90%,非核心模块≥70%
  2. 写测试:针对代码逻辑,设计测试用例。这里不是盲目写,而是「瞄准」未覆盖的代码
  3. 跑分析:用工具生成覆盖率报告。我常用gcov、JaCoCo、Istanbul这些
  4. 补测试:根据报告,补充遗漏的测试用例。循环直到达标

这个流程看起来简单,但坑很多。我曾经在一个项目中,团队把行覆盖率做到了95%,但分支覆盖率只有40%。为什么?因为大家只盯着「每行代码被执行了没」,却忽略了「每个分支条件都被测了没」。

避坑指南:我曾经犯过一个错误——只关注行覆盖率,忽略了分支覆盖率和条件覆盖率。结果一个if-else的分支没测到,线上出了严重bug。从那以后,我要求团队至少同时看行覆盖和分支覆盖两个指标。

1.5 覆盖率闭环管理

覆盖率不是测一次就完事的。它需要闭环管理。我画了一张图来说明:

覆盖率闭环管理流程 设定覆盖率目标 行覆盖≥90%,分支覆盖≥85% 编写测试用例 针对未覆盖代码设计测试 运行覆盖率分析 生成报告,识别未覆盖区域 补充测试用例 循环迭代,直到达标 未达标则循环 闭环管理要点 • 目标要量化 • 测试要可追溯 • 报告要可视化 • 迭代要有截止点 常见陷阱: 1. 目标定太高,团队 疲于应付 2. 只看数字,不看 测试质量 3. 忽略不可达代码 4. 没有定期复盘

闭环管理的关键,我总结为三点:

  • 目标可量化:别说什么「尽量覆盖」,要说「行覆盖≥85%,分支覆盖≥80%」
  • 过程可追溯:每次覆盖率报告都要存档,能回溯到具体版本
  • 结果可闭环:发现覆盖率不足,必须补充测试,不能放过

我的小技巧:在CI/CD流水线中,我会设置覆盖率门禁。如果本次提交导致覆盖率下降超过1%,流水线直接失败。这样能倒逼开发人员每次提交都考虑测试覆盖。

1.6 什么时候用TDD,什么时候用CDD?

这个问题我经常被问到。我的回答是:

  • 写新功能、新算法:用TDD。因为你需要先想清楚「这个功能应该怎么工作」
  • 做回归测试、维护老代码:用CDD。因为代码已经存在,你需要知道「哪些代码还没被测到」
  • 安全关键系统(汽车、医疗、航空):必须用CDD。因为标准要求覆盖率达标,比如ISO 26262要求MC/DC覆盖

我记得有一次给一个医疗设备项目做咨询。他们TDD做得很好,但客户审计时要求提供覆盖率报告。结果发现很多代码没覆盖到。后来我们引入CDD,花了两个月把覆盖率从65%提升到92%。客户很满意,审计也通过了。

所以,别纠结于「用哪个」。工具是死的,人是活的。根据场景选对工具,才是高手。


可可精品资料库