ExampleSpecification (intentionally ambiguous)inputs: result, taxrate, threshold output: tax relation: tax is <taxrate> percent of the profit, but the first <threshold> SEK is not taxed. glossary: profit - a positive result. Based on this specification, the following program was written. tax = 0 ; if result > 0 then % there is a profit tax = taxrate/100 * (result-threshold) ; end if ; Statement coverage requires only 1 test case: if result > 0, then all statements are executed. Branch coverage requires 2 test cases: it must also test the case result ≤ 0, that is the branch from the test directly to the end of the program. In contrast, statement coverage and branch coverage are the same (requiring 2 test cases) for the following program: if result > 0 then % there is a profit tax = taxrate/100 * (result-threshold) ; else tax = 0 ; end if ; Note: both criteria allow a test suite that can miss the error, namely that if 0 < result < threshold, then tax < 0. |
Example (infeasible path) Suppose that we write a quick and (very) dirty fix for the program above: tax = 0 ; if result > 0 then % there is a profit tax = taxrate/100 * (result-threshold) ; end if ; if tax < 0 then % oops tax = 0; end if ; There are 4 paths through this program: 1. result > 0, tax < 0 2. result > 0, tax ≥ 0 3. result ≤ 0, tax < 0 4. result ≤ 0, tax ≥ 0 But path 3 is infeasible: if result ≤ 0, then tax = 0 when we the program comes to the test tax < 0. Note: infeasible paths are not the same as dead code, and do occur also is well-structured programs. |
Example (continued) Suppose that we want to compute input for path 1. - start out with no constraints - pass the assignment "tax = 0" in the second if-statement - no constraints contain "tax" - add the test "tax < 0" to the constraints - pass the assignment "tax = taxrate/100 * (result-threshold)"; the new constraint is: taxrate/100 * (result-threshold) < 0. (- simplify the constraint: if taxrate is a positive symbolic constant, then the constraint becomes: result < threshold.) - add the test "result > 0"; the constraint is 0 < result < threshold. - pass the assignment "tax = 0", no constraints contain "tax". - we reached the beginning of the program with 0 < result < threshold. Exercise: try the same for path 3. You will note that the constraint becomes result ≤ 0 and 0 < 0. |
Example: a program doing a linear search
through an array A could begin with i = 1 ; found = false; while i ≤ A.length and not found do Ordinary branch coverage would require only one test case: the condition is first true, the program enters the loop, finds the item, and the next time the condition is fale. Condition coverage requires 2 test cases: one exiting the loop because i > A.length, and one because found is true. Note that a black-box partitioning test would also require these two cases. |