Category: Structural Testing And Code Coverage
-
Specification-based and structural testing: A running example
Let’s try specification-based testing and structural testing together on a real-world example: the leftPad() function from Apache Commons Lang. Left-pad a string with a specified string. Pad to a size of size. The method returns a left-padded string, the original string if no padding is necessary, or null if a null string is input. For example, if we give “abc” as the string…
-
Criteria subsumption, and choosing a criterion
You may have noticed that some of the criteria we have discussed are more rigorous than others. For example, a single test is enough to achieve 100% line coverage, but two tests are needed for 100% branch coverage. Some strategies subsume other strategies. Formally, a strategy X subsumes strategy Y if all elements that Y exercises are…
-
Handling loops and similar constructs
You may wonder what to do in the case of loops, such as for and while. The code block inside the loop may be executed different numbers of times, making testing more complicated. Think of a while(true) loop, which can be non-terminating. To be rigorous, we would have to test the program with the loop block executed one time, two times,…
-
Creating a test suite that achieves MC/DC
The question is how to (mechanically) select such test cases. Let’s continue using the same if statement from the CountWords program (from listing 3.4). The statement takes three booleans as input: (1) whether the current character is a letter and whether this letter is (2) “s” or (3) “r”. Generically, this is the same as the A && (B || C) example we just discussed.…
-
An abstract example
Let’s take a simple abstract example: if(A && (B || C)), where A, B, and C all evaluate to booleans. MC/DC dictates the following: If conditions have only binary outcomes (that is, true or false), the number of tests required to achieve 100% MC/DC coverage is N + 1, where N is the number of conditions in the decision (as shown by Chilenski [2001]). Note that N…
-
Complex conditions and the MC/DC coverage criterion
Devising test suites that maximize the number of bugs they can identify while minimizing the effort/cost of building the test suite is part of any tester’s job. The question is, what can we do about complex, lengthy if statements? Modified condition/decision coverage (MC/DC) is a good answer. The MC/DC criterion looks at combinations of conditions, as path…
-
Path coverage
A developer aiming for path coverage covers all the possible paths of execution of the program. While ideally this is the strongest criterion, it is often impossible or too expensive to achieve. In a single program with three conditions, where each condition could be independently evaluated to true or false, we would have 23 = 8 paths to cover. In…
-
Condition + branch coverage
Condition + branch coverage considers not only possible branches but also each condition of each branch statement. For example, the first if statement in the CountWords program contains three conditions: !Character.isLetter(str.charAt(i)), last == ‘s’, and last == ‘r’. Therefore, a developer aiming for condition + branch coverage should create a test suite that exercises each of those individual conditions being evaluated to true and false at least once and the entire branch…
-
Branch coverage
Branch coverage takes into consideration the fact that branching instructions (ifs, fors, whiles, and so on) make the program behave in different ways, depending how the instruction is evaluated. For a simple if(a && b) statement, having a test case T1 that makes the if statement true and another test case T2 that makes the statement false is enough to consider the branch covered. Figure 3.5 illustrates a…
-
Line coverage
A developer who aims to achieve line coverage wants at least one test case that covers the line under test. It does not matter if that line contains a complex if statement full of conditions. If a test touches that line in any way, the developer can count the line as covered.