2. 测试覆盖率类型:行覆盖率、分支覆盖率、条件覆盖率、路径覆盖率、MC/DC覆盖率
聊到测试覆盖率,很多人第一反应就是「代码跑了多少行」。嗯,这没错,但远远不够。我在实际项目中见过太多次了——行覆盖率100%,上线照样出事故。为什么?因为你没覆盖到真正的逻辑组合。
这一节,我把五种常用的覆盖率类型掰开揉碎讲清楚。每种我都会说说它的适用场景,以及我踩过的坑。
2.1 行覆盖率(Line Coverage)
行覆盖率是最基础的指标。说白了,就是看你的测试用例执行了多少行代码。
举个例子:
if (a > 0) {
b = 1; // 第3行
} else {
b = -1; // 第5行
}
c = b * 2; // 第7行
如果测试用例只传了 a = 5,那么第3行和第7行被执行了,第5行没执行。行覆盖率是 2/3 ≈ 66.7%。
2.2 分支覆盖率(Branch Coverage)
分支覆盖率看的是每个判断条件的真/假分支是否都被走到。它比行覆盖率更严格。
还是上面那段代码:
- 分支1:
a > 0为真 → 走第3行 - 分支2:
a > 0为假 → 走第5行
你需要两个测试用例:a = 5 和 a = -1,才能达到100%分支覆盖率。
2.3 条件覆盖率(Condition Coverage)
条件覆盖率更细了。它关注的是每个布尔子表达式(原子条件)的真假值。
看这个例子:
if (a > 0 && b < 10) {
// do something
}
这里有2个原子条件:a > 0 和 b < 10。条件覆盖率要求每个原子条件至少取一次真、一次假。
| 测试用例 | a > 0 | b < 10 | 结果 |
|---|---|---|---|
| a=5, b=3 | 真 | 真 | 真 |
| a=-1, b=3 | 假 | 真 | 假 |
| a=5, b=20 | 真 | 假 | 假 |
三个用例就能让两个原子条件都覆盖到真和假。但注意,条件覆盖率和分支覆盖率不是一回事——条件覆盖率100%了,分支覆盖率可能还是50%。
2.4 路径覆盖率(Path Coverage)
路径覆盖率是最「狠」的。它要求覆盖程序中所有可能的执行路径。
举个例子:
if (x > 0) {
// 路径A
}
if (y > 0) {
// 路径B
}
这里有4条路径:
- 路径1:A不执行,B不执行
- 路径2:A执行,B不执行
- 路径3:A不执行,B执行
- 路径4:A执行,B执行
所以实际项目中,路径覆盖率通常只用在关键模块,比如加密算法、协议解析这类核心逻辑。
2.5 MC/DC覆盖率(Modified Condition/Decision Coverage)
MC/DC是航空级软件(比如DO-178C标准)要求的覆盖率。它比条件覆盖率更严格,但比路径覆盖率更实用。
MC/DC的核心要求是:每个原子条件必须独立地影响整个判断的结果。
什么意思?看这个:
if (A && B) {
// 结果
}
MC/DC要求:
- 当B固定为真时,改变A的值,结果必须跟着变
- 当A固定为真时,改变B的值,结果必须跟着变
测试用例组合:
| A | B | 结果 | 说明 |
|---|---|---|---|
| 真 | 真 | 真 | 基准 |
| 假 | 真 | 假 | A独立影响 |
| 真 | 假 | 假 | B独立影响 |
3个用例就够,而不是条件覆盖率的4个。这就是MC/DC的巧妙之处——用最少的用例,验证每个条件的独立影响。
2.6 五种覆盖率的对比
我整理了一张表,方便你对比:
| 覆盖率类型 | 覆盖粒度 | 用例数量 | 适用场景 | 我的建议 |
|---|---|---|---|---|
| 行覆盖率 | 代码行 | 少 | 快速评估 | 别只看这个 |
| 分支覆盖率 | 判断分支 | 中等 | 常规项目 | 至少做到这个 |
| 条件覆盖率 | 原子条件 | 中等 | 复杂逻辑 | 配合分支一起用 |
| 路径覆盖率 | 完整路径 | 指数级 | 核心模块 | 只用在关键处 |
| MC/DC覆盖率 | 独立影响 | 线性增长 | 安全关键 | 航空级必备 |
2.7 知识体系结构图
下面这张图,帮你理清五种覆盖率之间的关系:
嗯,这张图把五种覆盖率的关系和选择建议都画出来了。你想想看,日常项目中,分支覆盖率做到100%已经能挡住大部分问题了。但如果你在做航空、医疗、自动驾驶这类安全关键系统,MC/DC覆盖率是绕不过去的坎。
我个人习惯是:先跑行覆盖率快速定位未执行的代码,再用分支覆盖率保证逻辑分支都走到,最后对核心模块做MC/DC。这样既高效又稳妥。
可可精品资料库