It's true that some expressions are amenable to restructuring, and such restructuring might reduce the effort involved in creating test-cases for the sole purpose of achieving MC/DC. However, you should consider the consequences of restructuring code for this purpose. In the case of a simple and statement (in C):
if (a && b) { code1(); } else { code2(); }
You could rewrite the expression to eliminate the multiple condition as below:
if (a) { if (b) { code1(); } else { code2(); } } else { code2(); }
Or for a different example (this time in Ada):
if a or else b then code1; else code2; end if;
becomes
if a then code1; else if b then code1; else code2; end if; end if;
Now code is being repeated, it's harder to review the circumstances under which a particular piece of code runs, and the traceability to the requirements just got a whole lot trickier.
The other thing that you might notice about the above two examples is that you haven’t reduced the number of test cases that are required. In the first version of the first example, you would need the following test vectors to achieve MC/DC:
a | b | |
V1 | TRUE | TRUE |
V2 | TRUE | FALSE |
V3 | FALSE | TRUE (or don’t care if you’re using masking MC/DC) |
(V1 and V3 test condition ‘a’, and V1 and V2 test condition ‘b’)
For the second version of the first example, you would need to test a
with TRUE
and FALSE
, and to test b
with TRUE
and FALSE
. This leads to exactly the same set of test cases as for the first version. A similar situation applies in the second example.