The statement you quoted is true, but not directly helpful due to the prevalence of short-circuiting operators in modern languages. It is not correct to interpret &&
or ||
in C-like languages as logical operators. Instead, they are control-flow operators and a sequence point. Other languages make this clearer (e.g. the logical and
vs. the control-flow andalso
in Standard ML).
For a program using only short-circuit operators, it is possible to interpret multiple condition coverage as equal to branch coverage and equal to simple condition coverage. Then, path coverage subsumes multiple condition coverage. This interpretation is essentially correct, but not very useful.
Multiple condition coverage is not fundamentally about the control flow of the program, but about the data flow. Condition coverage asks: the values of which boolean expressions have been covered? Multiple condition coverage is then interested in the combinations of boolean subexpressions within one decision operator. For the purpose of calculating this coverage metric, it can be sensible to disregard short-circuiting behaviour.
So in a condition without short-circuiting boolean operators or when disregarding short-circuiting behaviour, then it is clear that full path coverage for if (a & b) ...
can be obtained with only two cases (e.g. a=false, b=false
and a=true, b=true
), whereas test cases are missing for full multiple condition coverage (here: a=false, b=true
and a=true, b=false
).
One practical benefit of using condition coverage is to show that the condition can actually influence the decision outcome. If not, we might unexpectedly have dead code. For this, multiple condition coverage is not necessary, but modified condition/decision coverage is sufficient. For the if (a & b)
example, we would need three test cases for MC/DC: a=true, b=true
; a=true, b=false
; a=false, b=true
. Therefore, path coverage doesn't imply MC/DC coverage either.
One problem using any kind of condition coverage is that this metric can be easily gamed by using control flow operators instead of logical operators. Additionally, incrementally building a decision like bool d = true; d &= a; d &= b; if (d) ...
makes it non-obvious how a
and b
contribute to the decision. Therefore, condition coverage metrics are generally meaningless unless coupled to a specific coding style.