Top-down Testing
The top-down strategy starts with the top, or initial, module in the program. After this, there is no single right procedure for selecting the next module to be incrementally tested; the only rule is that to be eligible to be the next module, at least one of the module’s subordinate (calling) modules must have been tested previously.
Figure 2 is used to illustrate this strategy. A through L are the 12 modules in the program. Assume that module J contains the program’s I/O read operations and module I contains the write operations.
The first step is the testing of Module A. To
accomplish this, stub
modules representing B, C, and D must be written. Unfortunately,
the production of stub modules is often misunderstood; as evidence,
you may often see such statements as “a stub module need only write
a message stating ‘we got this far,’ ” and “in many cases, the dummy
module (stub) simply exits—without doing any work at all.” In most
situations, these statements are false. Since module A calls module B,
A is expecting B to perform some work; this work most likely is some
result (output arguments) returned to A. If the stub simply returns
control or writes an error message without returning a meaningful
result, module A will fail, not because of an error in A, but because
of a failure of the stub to simulate the corresponding module.
Moreover,
returning a “wired-in” output from a stub module is often
insufficient. For instance, consider the task of writing a stub
representing
a square-root routine, a database table-search routine, an “obtain
corresponding master-file record” routine, or the like. If the
stub returns a fixed wired-in output, but, not having the particular
value expected by the calling module during this invocation, the
calling
module may fail or produce a confusing result. Hence, the production
of stubs is not a trivial task.
Another consideration is the form in which test cases are presented
to the program, an important consideration that is not even mentioned
in most discussions of top-down testing. In our example, the
question is: How do you feed test cases to module A? Since the top
module in typical programs neither receives input arguments nor
performs input/output operations, the answer is not immediately
obvious. The answer is that the test data are fed to the module (module
A in this situation) from one or more of its stubs. To illustrate,
assume that the functions of B, C, and D are as follows: B—Obtain summary of transaction file.
C—Determine whether weekly status meets quota.
D—Produce weekly summary report.
A test case for A, then, is a transaction summary returned from
stub B. Stub D might contain statements to write its input data to a
printer, allowing the results of each test to be examined.
In this program, another problem exists. Since module A presumably
calls module B only once, the problem is how you feed more
than one test case to A. One solution is to develop multiple versions
of stub B, each with a different wired-in set of test data to be
returned to A. To execute the test cases, the program is executed
multiple times, each time with a different version of stub B. Another
alternative is to place test data on external files and have stub B read
the test data and return them to A. In either case, and because of the
previous discussion, you should see that the development of stub
modules is more difficult than it is often made out to be. Furthermore,
it often is necessary, because of the characteristics of the program,
to represent a test case across multiple stubs beneath the
module under test (i.e., where the module receives data to be acted
upon by calling multiple modules).
After A has been tested, an actual module replaces one of the
stubs, and the stubs required by that module are added. For
instance, Figure 3 might represent the next version of the
program.
After testing the top module, numerous sequences are possible. For
instance, if we are performing all the testing sequences, four examples
of the many possible sequences of modules are
- A B C D E F G H I J K L
- A B E F J C G K D H L I
- A D H I K L C G B F J E
- A B F J D I E C G K H L
If parallel testing occurs, other alternatives are possible. For
instance, after module A has been tested, one programmer could take
module A and test the combination A-B, another programmer could
test A-C, and a third could test A-D. In general, there is no best
sequence, but here are two guidelines to consider:
- If there are critical sections of the program (perhaps module
G), design the sequence such that these sections are added as
early as possible. A “critical section” might be a complex
module, a module with a new algorithm, or a module suspected
to be error prone.
- Design the sequence such that the I/O modules are added as
early as possible.
|