White box test design techniques (Part 3)

Loop Testing

Loops considered as one of the important control structures in any programming language. As we have seen in the previous blog post, loops make path testing difficult by increasing the number of possible paths in programs.

For example, If a program routine has one loop, each iteration through that loop reveals a new path. However in every iteration, the same code is getting traversed again and again. Hence even smaller routines can have potentially large number of paths. This makes the testing very difficult around loops.

Also most of the cases bugs in these loops will make certain mandatory paths unable to execute and sometimes even create unwanted paths. This implies the importance of paying little more attention on testing around loops.

There are different ways in which we can achieve loop coverage. These methods differ based on type of loop.

  • Single loops

These are loops in which their loop body contains no other loops (the innermost loop in case of nested).

In order to have loop coverage, testers should exercise the tests given below.

  • Test 1 :Design a test in which loop body shouldn’t execute at all (i.e. zero iterations)
  • Test 2 :Design a test in which loop–control variable be negative (Negative number of iterations)
  • Test 3 :Design a test in which loop iterates only once
  • Test 4 :Design a test in which loop iterates twice
  • Test 5 :Design a test in which loop iterates certain number of times , say m where m < maximum number of iterations possible
  • Test 6 :Design a test in which loop iterates one less than the maximum number of iterations
  • Test 7 :Design a test in which loop iterates the maximum number of iterations
  • Test 8 :Design a test in which loop iterates one more than the maximum number of iterations

Consider the below code example which applies all the conditions specified.

public class SimpleLoopTest {
    
private int[] numbers = {5,-77,8,-11,4,1,-20,6,2,10};
    
    /** Compute total of  positive numbers in the array
     *  @param numItems number of items to total.
     */
    public int findSum(int numItems)
    {
        int total = 0;
        if (numItems <= 10)
        {
            for (int count=0; count < numItems; count = count + 1)
            {
              if (numbers[count] > 0)
                 {
                    total = total + numbers[count];
                 }
            }                
        }
        return total;
    }

}

public class TestPass extends TestCase {
    
    public void testname() throws Exception {
        
        SimpleLoopTest s = new SimpleLoopTest();        
        assertEquals(0, s.findSum(0));    //Test 1
        assertEquals(0, s.findSum(-1));   //Test 2
        assertEquals(5, s.findSum(1));    //Test 3
        assertEquals(5, s.findSum(2));    //Test 4
        assertEquals(17, s.findSum(5));   //Test 5
        assertEquals(26, s.findSum(9));   //Test 6
        assertEquals(36, s.findSum(10));  //Test 7
        assertEquals(0, s.findSum(11));   //Test 8
    }

}

  • Nested Loops

A nested loop is a loop within a loop.

The outer loop changes only after the inner loop is completely finished / interrupted.

In this case, test cases should be designed in such a way that

  • Start at the innermost loop. Set all the outer loops to their minimum values.
  • Perform Simple loop testing on the innermost loop (Test3 / Test4 / Test5 / Test6 / Test7).
  • Continue till all the loops tested
  • Concatenated loops

Two loops are concatenated if it’s possible to reach one after exiting the other on same path from entrance to exit. Sometimes these two loops are independent to each other. In those cases we can apply the design techniques specified as part of single loop testing.

But if the iteration values in one loop are directly or indirectly related to the iteration values of another loop and they can occur on the same path, then we can consider them as nested loops.

  • Unstructured Loops

This kind of loops occurs through the use of code that jumps into and out of loops. These loops are also termed as knotted / Horrible (Beizer, 1984) loops. It is highly recommended to avoid these kind of loops/ redesign them in code.

Efficient testing of knotted loops are not practical in most of the scenarios.