“I beheld the wretch—the miserable monster whom I had created.”
MARY WOLLSTONECRAFT SHELLEY, Frankenstein
Each function should be designed, coded, and tested as a separate unit from the rest of the program. This is the essence of the top-down design strategy. When you treat each function as a separate unit, you transform one big task into a series of smaller, more manageable tasks. But how do you test a function outside of the program for which it is intended? You write a special program to do the testing. For example, Display 5.10 shows a program to test the function getInput
, which was used in the program in Display 5.9.
Driver Program
1 //Driver program for the function getInput.
2 #include <iostream>
3
4 void getInput(double& cost, int& turnover);
5 //Precondition: User is ready to enter values correctly.
6 //Postcondition: The value of cost has been set to the
7 //wholesale cost of one item. The value of turnover has been
8 //set to the expected number of days until the item is sold.
9
10 int main( )
11 {
12 using namespace std;
13 double wholesaleCost;
14 int shelfTime;
15 char ans;
16
17 cout.setf(ios::fixed);
18 cout.setf(ios::showpoint);
19 cout.precision(2);
20 do
21 {
22 getInput(wholesaleCost, shelfTime);
23
24 cout << "Wholesale cost is now $"
25 << wholesaleCost << endl;
26 cout << "Days until sold is now "
27 << shelfTime << endl;
28
29 cout << "Test again?"
30 << " (Type y for yes or n for no): ";
31 cin >> ans;
32 cout << endl;
33 } while (ans == 'y' || ans == 'Y');
34
35 return 0;
36 }
37 //Uses iostream:
38 void getInput(double& cost, int& turnover)
39 {
40 using namespace std;
41 cout << "Enter the wholesale cost of item: $";
42 cin >> cost;
43 cout << "Enter the expected number of days until sold: ";
44 cin >> turnover;
45 }
Sample Dialogue
Enter the wholesale cost of item: $123.45 Enter the expected number of days until sold: 67 Wholesale cost is now $123.45 Days until sold is now 67 Test again? (Type y for yes or n for no): y Enter the wholesale cost of item: $9.05 Enter the expected number of days until sold: 3 Wholesale cost is now $9.05 Days until sold is now 3 Test again? (Type y for yes or n for no): n
Programs like this one are called driver programs. These driver programs are temporary tools and can be quite minimal. They need not have fancy input routines. They need not perform all the calculations the final program will perform. All they need do is obtain reasonable values for the function arguments in as simple a way as possible—typically from the user—then execute the function and show the result. A loop, as in the program shown in Display 5.10, will allow you to retest the function on different arguments without having to rerun the program.
If you test each function separately, you will find most of the mistakes in your program. Moreover, you will find out which functions contain the mistakes. If you were to test only the entire program, you would probably find out if there were a mistake but may have no idea where the mistake is. Even worse, you may think you know where the mistake is but be wrong.
Once you have fully tested a function, you can use it in the driver program for some other function. Each function should be tested in a program in which it is the only untested function. However, it’s fine to use a fully tested function when testing some other function. If a bug is found, you know the bug is in the untested function. For example, after fully testing the function getInput
with the driver program in Display 5.10, you can use getInput
as the input routine in driver programs to test the remaining functions.
It is sometimes impossible or inconvenient to test a function without using some other function that has not yet been written or has not yet been tested. In this case, you can use a simplified version of the missing or untested function. These simplified functions are called stubs. These stubs will not necessarily perform the correct calculation, but they will deliver values that suffice for testing, and they are simple enough that you can have confidence in their performance. For example, the program in Display 5.11 is designed to test the function giveOutput from Display 5.9 as well as the basic layout of the program. This program uses the function getInput, which we already fully tested using the driver program shown in Display 5.10. This program also includes the function initializeScreen, which we assume has been tested in a driver program of its own, even though we have not bothered to show that simple driver program. Since we have not yet tested the function price, we have used a stub to stand in for it. Notice that we could use this program before we have even written the function price. This way we can test the basic program layout before we fill in the details of all the function definitions.
Program with a Stub
Sample Dialogue
This program determines the retail price for
an item at a Quick-Shop supermarket store.
Enter the wholesale cost of item: $1.21
Enter the expected number of days until sold: 5
Wholesale cost = $1.21
Expected time until so
Using a program outline with stubs allows you to test and then “flesh out” the basic program outline, rather than write a completely new program to test each function. For this reason, a program outline with stubs is usually the most efficient method of testing. A common approach is to use driver programs to test some basic functions, like the input and output functions, and then use a program with stubs to test the remaining functions. The stubs are replaced by functions one at a time: One stub is replaced by a complete function and tested; once that function is fully tested, another stub is replaced by a full function definition, and so forth until the final program is produced.
What is the fundamental rule for testing functions? Why is this a good way to test functions?
What is a driver program?
Write a driver program for the function introduction shown in Display 5.11.
Write a driver program for the function addTax
from Self-Test Exercise 11.
What is a stub?
Write a stub for the function whose function declaration is given next. Do not write a whole program, only the stub that would go in a program. (Hint: It will be very short.)
double rainProb(double pressure, double humidity,
double temp);
//Precondition: pressure is the barometric
//pressure in inches of mercury,
//humidity is the relative humidity as a percent, and
//temp is the temperature in degrees Fahrenheit.
//Returns the probability of rain, which is a number
//between 0 and 1.
//0 means no chance of rain. 1 means rain is 100%
//certain.