首先,Decision和Condition的区别。
Condition 是一个原子布尔表达式,不能分解为更简单的布尔表达式。例如:a(如果 a 是布尔值)。
Decision 是具有零个或多个布尔运算符的条件组合。没有运算符的决定也是一个条件。例如:(a or b) and c 也可以是 a and b 或只是 a。
举个简单的例子
if(decision) {
//branch 1
} else {
//branch 2
}
您需要两个测试来覆盖两个分支。这就是决策覆盖率或分支覆盖率。如果决策是一个条件(即只是a),也称为基本条件覆盖,即单个条件的两个分支的覆盖。
decision 可以分解为条件。
举个例子
decision = (a or b) and c
决策覆盖率将通过
实现
但其布尔子表达式的所有组合的排列是全条件覆盖或多条件覆盖),它是basic的复合条件覆盖:
| a | b | c |
| 0 | 0 | 1 |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 0 | 1 | 0 |
| 1 | 0 | 1 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
| 1 | 1 | 0 |
这将是相当多的测试,但其中一些是多余的,因为某些条件已被其他条件覆盖。这反映在 Modified Condition/Decision Coverage (MC/DC) 中,它是 条件覆盖率 和 功能覆盖率 的组合。
对于 MC/DC,每个条件都必须独立影响结果。通过上述测试(全部为 0 或全部为 1),我们忽略了这样一个事实,即如果 a 和 b 为 0,c 值无关紧要,或者,如果 a 和 c 为 1,b 值无关紧要。
所以你应该坐下来,动动脑筋,想一想哪些组合的总体结果 R 是 1 或 0。
| a | b | c | a or b | c | R | eq
1 | 0 | 0 | 0 | 0 | 0 | 0 | A
2 | 0 | 0 | 1 | 0 | 1 | 0 | B
3 | 0 | 1 | 0 | 1 | 0 | 0 | A
4 | 0 | 1 | 1 | 1 | 1 | 1 | C
5 | 1 | 0 | 0 | 1 | 0 | 0 | A
6 | 1 | 0 | 1 | 1 | 1 | 1 | D
7 | 1 | 1 | 0 | 1 | 0 | 0 | A
8 | 1 | 1 | 1 | 1 | 1 | 1 | D
最后一列显示等价类:
- A:c = 0,结果为0,a和b都没有影响
- B:a,b = 0,结果为0,c没有影响
- C: b,c = 1,结果为 1,a 没有影响
- D:a,c = 1,结果为1,b没有影响
对于 B 和 C,选择哪个非常明显,对于 A 和 D 则不然。对于每个您必须检查的情况,如果我替换运算符,即或 -> 和,和 -> 或,会发生什么这会影响(子)决策的结果吗?如果结果会受到影响,你就有了候选人 - 如果没有,你没有。
- A : (0 and/or 0) and/or 0 -> 没关系
- A : (0 and 1) vs (0 or 1) -> 很重要! -> 候选人
- A : (1 and 0) vs (1 or 0) -> 很重要! -> 候选人
- A : (1 and/or 1) -> 没关系
- D : (1 and 0) vs (1 or 0) -> 确实很重要 -> 候选人
- D : (1 和 1) -> 没关系
所以你得到了上面提到的最终测试集:
- a = 0, b = 1, c = 0 -> 错误分支 (A) OR a = 1, b = 0, c = 0
- a = 0, b = 0, c = 1 -> 错误分支 (B)
- a = 0, b = 1, c = 1 -> 真正的分支 (C)
- a = 1, b = 0, c = 1 -> 真正的分支 (D)
尤其是后一种测试——改变操作符——可以使用像变异测试这样的工具来完成,它不仅可以替换操作符,还可以做更多的事情,即翻转操作数、删除语句、更改执行顺序、替换返回值等等。对于代码的每次更改,它都会验证测试是否真的失败了。这是测试套件质量的良好指标,并确保代码不仅被覆盖,而且您对代码的测试实际上是有效的。
关于术语,我在某处找不到“复合决策覆盖”一词。在我看来,“复合决策”是条件的复合,换句话说:条件的复合。