The approach is to write a program that passes input data to the unit under test and compares the output to truth. The input comes from a loop index for 100% or uniform testing, from a random number generator from Monte Carlo testing, from carefully selected input conditions coded directly in the program or from a file of manufactured data. The output is determined to be good or bad by comparing it to some trusted results, using an inverse function, or comparing it to a file containing data that is defined to be correct.
You may have wondered why I tested the Cosine function that uses degrees instead of the Sine function that uses radians. I did that simply because it tests several features of the Meridian TRIG package at once. The Sin and Units_Convert functions are nested in the Cos function. As the index goes from -5.0 degrees to 370.0 degrees, it uses the Units_Convert function to convert from degrees to radians at each of those angles, so there is no need for me to waste time separately testing the Units_Convert function. I know the Cos function in the Meridian TRIG body calls the Sin function, so the Sin function is tested at the same time.
White-box testing saves time, but it has its disadvantages, too. If you are testing several things at once, and you get the right answer, it is a pretty good indication that everything works. If you don't get the right answer, then you can't be sure what went wrong. If the Cos_Test results are wrong, it could be because there is an error in the Cos function, the Sin function, or the Units_Convert function. Then you will have to test Sin and Units_Convert separately, using a similar test driver program, to isolate the error.
On the other hand, you could argue that white-box testing is more reliable because you know more about the thing you are testing, and will be more alert to potential problems. For example, if you are white-box testing a Tan function, and know that it computes Sin/Cos, you may be more likely to remember to check for conditions that may cause a division by zero than you would if it was just a black box.
It really comes down to the person doing the testing, rather than the method used. Either method, consciously applied, will do the job. Either method, poorly done, will fail to catch errors.
A stub is a simple routine that takes the place of the real routine. It may be a null procedure, or it may simply write a message to the screen that says, "I was called!" These stubs let you check the interfaces and higher levels of the program.
When I was working on the Show program, I wanted to test the concept of adding the command-line input to the main program before I had figured out how to make the command line work. I did this using the test stubs shown in Figures 43 and 44. Figure 43 just returned a constant string. When I verified that it worked, then I used Figure 44 to see what happened with various inputs. If I had just leaped into trying to implement the Get_Command_Line procedure, and found that Show didn't work, I wouldn't have been able to tell if the error was in Show or Get_Command_Line. The two test stubs were so simple, I could have more confidence that they were correct, and could focus my attention on Show, where the problem probably was.
Test stubs don't need be limited to fixed data or user- supplied data. You can write test stubs that take input data from a file. Test stubs need not be just input simulators. They can also display or record data sent to them. Sometimes stubs count how many times they are called, or record the maximum or minimum values they receive. They can set a flag after they have been called a certain number of times. What you can do with a stub is limited only by your imagination.
Let's use and example to show how drivers and stubs can be used to check a program. Suppose you are writing a program that replays data from a test flight. The user enters the number of the flight he wants to replay. A procedure then searches a data base to see which reel of tape contains the data for that flight, and tells the computer operator to mount that reel. Suppose the wrong reel is consistently mounted. Where is the problem?
If you think the problem is in the routine that looks up the reel number for a given flight, you can use a test driver. The test driver could be as simple as the one shown in Figure 45. It asks you for a flight number and tells you what reel it is on. It will tell you if the Lookup routine works or not.
If there are symptoms that suggest that the Lookup routine is working correctly, is getting wrong input data, or maybe isn't being called at all, you can replace it with a stub like the one shown in Figure 46. Whenever it is called, it writes, "What reel contains flight number XXX? ", where XXX is the parameter that was passed to the stub. You enter YYY and press return. Then you can isolate the problem. Was XXX the flight number the user entered, or was the wrong parameter passed to the stub? Did the operator get a message to mount reel YYY, or was he told to mount a different reel?
A demo program is just a quick confidence check. It may not check every part of the package, and it usually involves a user interface. For example, a demo program might ask the user to enter an angle in degrees, and then print the sine, cosine, and tangent of the angle. The user can run this program a couple of times and observe the results, just to see if the program compiles and runs.