1.2 Testing boundary conditions

Selection and repetition control structures use the results of conditions to determine their actions. 

  • These conditions, if incorrect, are likely to result in major errors. 
  • For this reason all conditions require close examination during testing. 
  • We should ensure each condition is checked using test data above, below and equal to any values upon which decisions are based. 
  • This is known as decision coverage testing. 
    • For example, the condition Counter < 2 should be tested using a value greater than 2, less than 2 and equal to two.

The situation becomes more complicated as the complexity of the condition increases. 

  • Many conditions contain logical or and and operators and others are based on values that are calculated by previous processes. 
  • In these cases, it is often appropriate to test the condition in isolation from the rest of the algorithm or code. 
  • Once its correctness has been established it can be included in the code with confidence.

Fortunately, the sets of test data designed to check each pathway through the algorithm will also check the upper and lower values of each condition. 

  • This leaves the task of testing the precise values on which decisions rest. 
  • Additional test data sets should be added to the path coverage data sets to ensure this occurs.

CASE STUDY

In chapter 5, we developed a function for validating integers; the algorithm is reproduced below in Fig 6.4. Let us develop a set of test data that performs both path and decision coverage testing of this algorithm. Remember we are testing the algorithm for correctness, this does not ensure it meets the original design specifications nor does it ensure it operates efficiently. Later in this chapter, we examine methods for evaluating these issues.

There are four inputs into this function; InputString, Min, Max and Default and a single output; ValidateInteger. Each test data set therefore requires four values together with a single expected output. The documentation detailing our test data sets should also include a reason for each set’s inclusion.

The algorithm contains a single repetition and two binary selection statements. Three conditions in all, so there will be a maximum of eight (23) possible execution paths to test. Because of the repetition, it is possible for a single set of test data to check more than one path so it is likely that less than eight sets of test data will be needed to perform our path coverage tests.

 


Let us examine each of the eight paths and determine which should be possible and which should not be possible:

  • Eamining the above table reveals that we have six possible paths, namely paths 1, 2, 3, 4, 5 and 6. 
  • However, only four of these six paths should ever be executed if our algorithm operates correctly. 
  • Paths 3 and 4 both require similar inputs containing no valid digits and 
  • paths 5 and 6 both require InputString to be Null. 
  • We therefore require four sets of test data to perform our path coverage test.
Possible test data to cover these paths could be:


We now have test data to perform path coverage testing. Let us now consider the creation of further test data to perform decision coverage testing. There are three decisions to consider - the loop’s terminating condition and the two conditions within the binary selection statements.

  • Loop condition- there are only two possibilities here. Either there are more characters or there are not. Our existing test data includes both these possibilities.
  • First selection condition- characters are either digits or they are not digits. Again, our existing test data contains characters that are and characters that are not digits.
  • Second selection condition- expanding this condition yields three sub conditions. We do not currently have test data for each of these conditions.

As our existing test data covers the loop and first selection condition we need only consider the second selection condition in detail. This condition contains four identifiers - StringInteger, ValidInt, Min and Max. The first sub-condition, StringInteger is empty, requires a specific single value to evaluate to true. The second part of the condition is more involved; the value held in ValidInt must not lie within the range Min to Max, in other words, it must be outside this range. The most likely mathematical interpretation of this being ValidInt must be less than Min or greater than Max.

We can use a decision tree to graphically depict this second selection condition (see Fig 6.5).

The tree shows four possible methods of obtaining a result – three of these results being True and one being False. We need to design test data for each of these branches as well as data that matches the precise values within the condition.

We already have test data that should result in StringInteger being empty (InputString set to Null or abc) and not empty (InputString set to 9a3). We also have test data that results in ValidInt being greater than Max
(InputString set to 9a3 when Min is 0 and Max is 10) and ValidInt lying between Min an md Max (InputString set to 9a3 when Min is 0 and Max is 100). We require a test data set to check when ValidInt is less than Min; say InputString set to 9a3 when Min is set to 100 and Max is set to 200.

We also require test data sets to check the precise values within the condition.  

  • StringInteger equal to empty has already been dealt with; 
  • we require test data to check when ValidInt is equal to Min and again when it is equal to Max. 
  • We could use an InputString of 9a3 with Min being 93 and Max being 100 to ensure the Min part of the condition is correct. In addition, we could use an InputString of 9a3 with Min being 0 and Max being 93 to ensure the Max part of the condition is correct.


Comments