首先, Decision和Condition的区别。
条件是一个原子布尔表达式,不能分解为更简单的布尔表达式。例如:(a
如果a
是布尔值)。
决策是具有零个或多个布尔运算符的条件的组合。没有运算符的决定也是一个条件。例如:(a or b) and c
但也a and b
或只是a
。
举个简单的例子
if(decision) {
//branch 1
} else {
//branch 2
}
您需要两个测试来覆盖两个分支。那就是决策覆盖或分支覆盖。如果决策是一个条件(即只是a
),也称为基本条件覆盖,即单个条件的两个分支的覆盖。
decision
可以分解为条件。
举个例子
decision = (a or b) and c
决策覆盖率将通过
但是其布尔子表达式的所有组合的排列是全条件覆盖或多条件覆盖),它是基本条件覆盖的复合:
| 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 |
那将是相当多的测试,但其中一些是多余的,因为某些条件已被其他条件覆盖。这反映在修改后的条件/决策覆盖率(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 and 1) -> 没关系
所以你得到了上面提到的最终测试集:
- a = 0, b = 1, c = 0 -> 错误分支 (A) 或 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)
尤其是后一种测试——改变操作符——可以使用像变异测试这样的工具来完成,它不仅可以替换操作符,还可以做更多的事情,即翻转操作数、删除语句、更改执行顺序、替换返回值等。对于代码的每次更改,它都会验证测试是否确实失败。这是测试套件质量的良好指标,并确保代码不仅被覆盖,而且您的代码测试实际上是有效的。
关于术语,我在某处找不到“复合决策覆盖”一词。在我看来,“复合决策”将是条件的复合,换句话说:条件的复合。