Software Testing


Overview

To frame our discussion, consider:

Why do we need a conceptual structure to guide the testing process?

How do black-box and white-box testing differ?

What is the economic guidelines of software testing, and how does it relate to different methods?


OUTLINE


What is the purpose of software testing?

The purpose of software testing is

a. To demonstrate that the product performs each function intended;
b. To demonstrate that the internal operation of the product performs according to specification and all internal components have been adequately exercised;
c. To increase our confidence in the proper functioning of the software.
d. To show the product is free from defect.
e. All of the above.

Testing in the Lifecycle

Testing in the LIfecycle

Unit TestingChecks each coded module for the presence of bugs. Unit testing's purpose is to ensure that each as-built module behaves according to its specification defined during detailed design.
Integration Testing Interconnects sets of previously tested modules to ensure that the sets behave as well as they did as independently tested modules. Integration testing's purpose is to ensure that each as-built component behaves according to its specification defined during preliminary design.
System Testing Checks that the entire software system embedded in its actual hardware environment behaves according to the requirements document.
Unit Test Planninggenerates and documents plans and procedures to test each module independently and thoroughly.
Integration Test Planning generates and documents plans and procedures to effect an orderly system integration.
System Test Planningdevelopment and documentation of test plans and procedures. Examination of the SRD to determine whether or not it is verifiable (is it possible to establish that the software meets the SRD description).

Objectives

Testing cannot show the absence of defects, it can only show that software defects are present.
  1. Testing is a process of executing a program with the intent of finding an error.

  2. A good test case is one that has a high probability of finding an as yet undiscovered error.

  3. A successful test is one that uncovers an as yet undiscovered error.

A Problem of Economics

Industry Average (from around '86) - 30-85 defects/KLOC
Extensive Testing - .5-3 defects/KLOC

With large systems, it is almost always true that more testing will find more defects. The question is not whether all the defects have been found, but whether the cost of discovering the remaining defects can be justified. Hence, strategies for testing should be adopted that optimize the effort expended.

Testing Principles

  1. All tests should be traceable to customer requirements.
  2. Tests should be planned long before testing begins.
  3. 80% of errors are traceable to 20% of the modules (Pareto Principle - Error prone modules)
  4. Testing should begin in the small and progress to larger components.
  5. Exhaustive testing is NOT possible.
  6. Testing is more effective when conducted by an independent party. (SQA?)

White-Box Testing

White-box (glass-box) testing is a test case design method that uses the control structure of the procedural design to derive test cases. With white-box methods, tests cases are derived that:

1) guarantee all independent paths in a module have been tested (exercised) at least once;

2) exercise all logical decisions for both true and false conditions;

3) execute all loops at their boundary values and within their operational bounds;

4) exercise internal data structures to ensure their validity.


Basis Path Testing

The basis path method allows for the construction of test cases that are guaranteed to execute every statement in the program at least once. This method can be applied to detailed procedural design or source code.

Method

1. Draw the flow graph corresponding to the procedural design or code.

2. Determine the cyclomatic complexity of the flow graph.

3. Determine the basis set of independent paths. (The cyclomatic complexity indicates the number of paths required.)

4. Determine a test case that will force the execution of each path.

Flow Graphs

Sequence
IF
While
Repeat
Case

Example

Procedure Average
* This procedure computes the average of 100 or fewer
numbers that lie between bounding values.  It also
computes the sum and the total number of valid entries.
INTERFACE RETURNS  average, total.input, total.valid;
INTERFACE ACCEPTS  value, minimum, maximum;
TYPE  value[1:100] IS SCALAR ARRAY;
TYPE average, total.input, total.valid, minimum, maximum,
sum IS SCALAR;
TYPE  i IS INTEGER;

i=1;
total.input=total.valid=0;
sum=0;
DO WHILE value[i]<>-999 and total.input<100 
increment total.input by
1; IF value[i]>=minimum AND value[i]<=maximum
     THEN increment total.valid by 1;
             sum=sum+value[i]
     ELSE  skip
ENDIF
increment i by 1;
ENDDO
IF total.valid>0
     THEN average=sum/total.valid;
     ELSE average=-999;
ENDIF
END AVERAGE

Step 1: Construct Flow Graph
a) Identify predicate nodes

Procedure Average
* This procedure computes the average of 100 or fewer
numbers that lie between bounding values.  It also
computes the sum and the total number of valid entries.
INTERFACE RETURNS  average, total.input, total.valid;
INTERFACE ACCEPTS  value, minimum, maximum;
TYPE  value[1:100] IS SCALAR ARRAY;
TYPE average, total.input, total.valid, minimum, maximum,
sum IS SCALAR;
TYPE  i IS INTEGER;
i=1;
total.input=total.valid=0; { 1 }
sum=0;
DO WHILE 

value[i]<>-999  { 2}

and 

total.input<100 { 3}

increment total.input by 1;  { 4 }
IF 

value[i]>=minimum   { 5}

AND 

value[i]<=maximum  { 6}

     THEN increment total.valid by 1;  { 7 }
             sum=sum+value[i]
     ELSE  skip

ENDIF
increment i by 1;  { 8 }

ENDDO  { 9 }

IF total.valid>0  { 10 }

     THEN average=sum/total.valid;  { 11 }

     ELSE average=-999;  { 12 }

ENDIF  { 13 }
END AVERAGE


b) Draw flow graph

Flow Graph for Procedure Average

Step 2: Determine Cyclomatic Complexity

V(G) = E - N + 2

V(G) = 17 - 13 + 2 = 6

Step 3: Determine the basis set of independent paths.

1-2-10-11-13

1-2-10-12-13

1-2-3-10-11-13

1-2-3-4-5-8-9-2 ...

1-2-3-4-5-6-8-9-2 ...

1-2-3-4-5-6-7-8-9-2 ...

Step 4: Prepare test cases.

PathTest Case
1-2-10-11-13
1-2-10-12-13
1-2-3-10-11-13
1-2-3-4-5-8-9-2 ...
1-2-3-4-5-6-8-9-2 ...
1-2-3-4-5-6-7-8-9-2 ...

Loop Testing

Simple LoopsThe following set of tests should be applied to simple loops, where n is the maximum number of allowable passes:

1. Skip the loop entirely.

2. Only one pass through the loop.

3. Two passes through the loop.

4. m passes through the loop where m<n.

5. n-1, n, n+1 passes through the loop

Nested Loops1. Start with the innermost loop. Set all other loops to minimum values.

2. Conduct simple loop tests for the innermost loop while holding the outer loops at their minimum iteration values.

3. Work outward, conducting tests for the next loop, but keeping all other outer loops at this minimum iteration count.

4. Continue until all loop have been tested.

Concatenated LoopsConcatenated loops can be tested using the approach defined for simple loops, if the loops are independent. If the loop counter from a loop i is used as the initial value for loop I+1 then the loops are not independent. When loops are not independent use the concatenated loop strategy.
Unstructured LoopsRedesign the loops so they are one of the above categories.

Black Box Testing

Black box testing methods focus on the functional requirements of the software. Tests sets are derived that fully exercise all functional requirements. This strategy tends to be applied during the latter part of the lifecycle.

Tests are designed to answer questions such as:

1) How is functional validity tested?

2) What classes of input make good test cases?

3) Is the system particularly sensitive to certain input values?

4) How are the boundaries of data classes isolated?

5) What data rates or volumes can the system tolerate?

6) What effect will specific combinations of data have on system operation?

Equivalence Partitioning

This method divides the input of a program into classes of data. Test case design is based on defining an equivalent class for a particular input. An equivalence class represents a set of valid and invalid input values.

Guidelines for equivalence partitioning -

1) If an input condition specifies a range, one valid and two invalid equivalence classes are defined.

2) If an input condition requires a specific value, one valid and two invalid equivalence classes are defined.

3) If an input condition specifies a member of a set, one valid and one invalid equivalence class are defined.

4) If an input condition is boolean, one valid and one invalid class are defined.

Example

Consider an automated banking application. The user can dial the bank from a personal computer, provide a six-digit password, and follow with a series of keyword commands that activate the banking function. The software for the application accepts data in the following form:

Area CodeBlank or three-digit number
PrefixThree-digit number, not beginning with 0 or 1
SuffixFour-digit number
PasswordSix-character alphanumeric
Commands"Check", "deposit", "pay", etc.


Data Item
Input Condition
Remarks
Area CodebooleanThe area code may or may not be present
rangeValues between 200 and 999 with area codes requiring 0, 1 in second position
PrefixrangeSpecified value > 200
SuffixvalueFour-digit length
PasswordbooleanPassword may or not be present
valueSix-character string
Commandsset


Data Item
Input Condition
Equivalence Class
Area Codeboolean1) no area code given
2) area code given
range1) valid - in range specified
2) invalid - greater
3) invalid - less than
Prefixrange1) valid - between 200 and 999 (inclusive)
2) invalid - greater than 999
3) invalid - less than 200
Suffixvalue1) valid - a four-digit number
2) invalid - five-digit number
3) invalid - three-digit number
Passwordboolean1) no password given
2) password given
value1) valid - a six-character string
2) invalid - five-character string
3) invalid - seven-character string
Commandsset 1) valid - command in command set
2) invalid - command not in command set

Boundary Value Analysis

Boundary value analysis is complementary to equivalence partitioning. Rather than selecting arbitrary input values to partition the equivalence class, the test case designer chooses values at the extremes of the class. Furthermore, boundary value analysis also encourages test case designers to look at output conditions and design test cases for the extreme conditions in output.

Guidelines for boundary value analysis -

1) If an input condition specifies a range bounded by values a and b, test cases should be designed with values a and b, and values just above and just below and b.

2) If an input condition specifies a number of values, test cases should be developed that exercise the minimum and maximum numbers. Values above and below the minimum and maximum are also tested.

3) Apply the above guidelines to output conditions. For example, if the requirement specifies the production of an table as output then you want to choose input conditions that produce the largest and smallest possible table.

4) For internal data structures be certain to design test cases to exercise the data structure at its boundary. For example, if the software includes the maintenance of a personnel list, then you should ensure the software is tested with conditions where the list size is 0, 1 and maximum (if constrained).

Example

Data ItemInput Condition Remarks
Area CoderangeValues between 200 and 999 with area codes requiring 0, 1 in second position

Test Cases:
200, 910 (valid end-points)
199, 912 (value below and above)

PrefixrangeSpecified value > 200

Test Cases:
201 (minimum)
999 (maximum)
200 (invalid, just below)

SuffixvalueFour-digit length

Test Cases:
0000 (minimum)
9999 (maximum)

PasswordvalueSix-character string

Test Cases:

Commandsset Test Cases:


Cause-Effect Graphs

A weakness of the two methods is that do not consider potential combinations of input/output conditions. Cause-effect graphs connect input classes (causes) to output classes (effects) yielding a directed graph.

Guidelines for cause-effect graphs -

1) Causes and effects are listed for a modules and an identifier is assigned to each.

2) A cause-effect graph is developed (special symbols are required).

3) The graph is converted to a decision table.

4) Decision table rules are converted to test cases.

Sample Symbols

IdentityCause and Effect Identity
NotCause and Effect Not
OrCause and Effect Or
And Cause and Effect And


Go To Lecture [Outline] [Overview]

Go To [Course Outline]