Control Flow Coverage
Control Flow Coverage
In control flow testing, different levels of test coverage are defined. By "coverage" we mean the
percentage of the code that has been tested vs. that which is there to test. In control flow testing we define
coverage at a number of different levels.
Level 0 random
That level is defined as "test whatever you test; let the users test the rest." Boris Beizer wrote
"testing less than this [100% statement coverage] for new software is unconscionable and should
be criminalized. ... In case I haven't made myself clear, ... untested code in a system is stupid,
shortsighted, and irresponsible."
The lowest coverage level is "100% statement coverage" (sometimes the "100%" is dropped and is
referred to as "statement coverage"). This means that every statement within the module is
executed, under test, at least once. While this may seem like a reasonable goal, many defects may
be missed with this level of coverage. Consider the following code snippet:
if (a>0) {x=x+1;}
if (b==3) {y=0;}
While a single test case is sufficient to test every line of code in this module (for example, use a=6
and b=3 as input), it is apparent that this level of coverage will miss testing many paths. Thus,
statement coverage, while a beginning, is generally not an acceptable level of testing.
Even though statement coverage is the lowest level of coverage, even that may be difficult to achieve in
practice. Often modules have code that is executed only in exceptional circumstances-low memory, full
disk, unreadable files, lost connections, etc. Testers may find it difficult or even impossible to simulate
these circumstances and thus code that deals with these problems will remain untested.
Level 2 branch coverage
The next level of control flow coverage is "100% branch coverage." At this level enough test cases
are written so that each decision that has a TRUE and FALSE outcome is evaluated at least once.
In the previous example this can be achieved with two test cases (a=2, b=2 and a=4, b=3).
Case statements with multiple exits would have tests for each exit. Note that decision coverage
does not necessarily guarantee path coverage but it does guarantee statement coverage.
Level 3 decision coverage
Not all conditional statements are as simple as the ones previously shown. Consider these more
complicated statements:
if (a>0 && c==1) {x=x+1;}
if (b==3 || d<0) {y=0;}
To be TRUE, the first statement requires a greater than 0 and c equal 1. The second requires b
equal 3 or d less than 0.
In the first statement if the value of a were set to 0 for testing purposes then the c==1 part of the
condition would not be tested. (In most programming languages the second expression would not
even be evaluated.) The next level of control flow coverage is "100% decision coverage." At this
level enough test cases are written so that each condition that has a TRUE and FALSE outcome
that makes up a decision is evaluated at least once. This level of coverage can be achieved with
two test cases (a>0, c=1, b=3, d<0 and a0, c1, b3, d0). Condition coverage is usually better
than decision coverage because every individual condition is tested at least once while decision
coverage can be achieved without testing every condition.
Level 4 decision/condition coverage
We can achieve decision coverage with two test cases (x=TRUE, y=FALSE and x=FALSE,
y=TRUE) but note that with these choices of data values the conditionedStatement will never be
executed. Given the possible combination of conditions such as these, to be more complete "100%
decision/condition" coverage can be selected. At this level test cases are created for every
condition and every decision.
Level 5 multiple condition coverage
To be even more thorough, consider how the programming language compiler actually evaluates
the multiple conditions in a decision. Use that knowledge to create test cases yielding "100%
multiple condition coverage."
if (a>0 && c==1) {x=x+1;}
if (b==3 || d<0) {y=0;}
// note: || means logical OR
c=1,
c=1,
c1,
c1,
b=3,
b=3,
b3,
b3,
d<0
d0
d<0
d0
Achieving 100% multiple condition coverage also achieves decision coverage, condition
coverage, and decision/condition coverage. Note that multiple condition coverage does not
guarantee path coverage.
Level 6 limited path coverage
When a module has loops in the code paths such that the number of paths is infinite, a significant
but meaningful reduction can be made by limiting loop execution to a small number of cases. The
first case is to execute the loop zero times; the second is to execute the loop one time, the third is
to execute the loop n times where n is a small number representing a typical loop value; the fourth
is to execute the loop its maximum number of times m. In addition you might try m-1 and m+1.
Finally we reach the highest level, which is "100% path coverage." For code modules without
loops the number of paths is generally small enough that a test case can actually be constructed for
each path. For modules with loops, the number of paths can be enormous and thus pose an
intractable testing problem.
2. To choose the next path, change the outcome of the first decision along the baseline path while
keeping the maximum number of other decisions the same as the baseline path.
ABDEGKMQS
ACDEGKMQS
ABDFILORS
ABDEHKMQS
ABDEGKNQS
ACDFJLORS
ACDFILPRS
Structured testing calls for the creation of a test case for each of these paths. This set of test cases will
guarantee both statement and branch coverage.
Note that multiple sets of basis paths can be created that are not necessarily unique. Each set, however,
has the property that a set of test cases based on it will execute every statement and every branch.
Control flow Example
boolean evaluateBuySell (TickerSymbol ts) {
s1;
s2;
s3;
if (c1) {s4; s5; s6;}
else {s7; s8;}
while (c2) {
s9;
s10;
switch (c3) {
case-A:
s20;
s21;
s22;
break; // End of Case-A
case-B:
s30;
s31;
if (c4) {
s32;
s33;
s34;
}
else {
s35;
}
break; // End of Case-B
case-C:
s40;
s41;
break; // End of Case-C
case-D:
s50;
break; // End of Case-D
} // End Switch
s60;
s61;
s62;
if (c5) {s70; s71; }
s80;
s81;
} // End While
s90;
s91;
s92;
return result;
10
11
C1
C2
C3
C4
N/A
True
N/A
False True
N/A
False True
False False
False True
N/A
False
False True
N/A
False
False True
True
False
False True
N/A
True
C5
False
12