The art of software testing. Myers (2nd edition) (2004) (811502), страница 19
Текст из файла (страница 19)
Hence, the safest approach is to add test cases to those ofFigure 5.6Supplemental boundary-value-analysistest cases for BONUS.Testcase5InputESIZE = 3 DSIZE = 2EMPTAB6Expected outputERRCODE = 0DEPTTABALLYED36 14,999.99D3355,400.01BESTED33 15,000.00D3655,400.01CELTOED33 15,000.01EMPTABESIZE = 1 DSIZE = 1EMPTABCHIEFD99 99,899.99ALLYED3615,199.99BESTED3315,100.00CELTOED3315,100.01ERRCODE = 0DEPTTABMESIZE, DSIZE, and DEPTTAB areunchangedD99ESIZE, DSIZE, and DEPTTAB areunchanged99,000.00EMPTABCHIEF7D9999,999.99ERRCODE = 2ESIZE = 2 DSIZE = 2EMPTABMDEPTTABDOLEED67 10,000.00D6620,000.00FORDED22 33,333.33D6720,000.00ESIZE, DSIZE, and DEPTTAB areunchangedEMPTAB104DOLEED6710,000.00FORDED2233,333.33Module (Unit) Testing105Figure 5.5. In doing this, the goal is to design the smallest number oftest cases necessary to cover the boundary conditions.
The three testcases in Figure 5.6 accomplish this. Test case 5 covers conditions 7,10, 14, 17, 18, 19, and 20; test case 6 covers conditions 1, 4, and 23;and test case 7 covers condition 24.The premise here is that the logic-coverage, or white-box, testcases in Figure 5.6 form a reasonable module test for procedureBONUS.Incremental TestingIn performing the process of module testing, there are two key considerations: the design of an effective set of test cases, which was discussed in the previous section, and the manner in which the modulesare combined to form a working program. The second considerationis important because it has implications for the form in which module test cases are written, the types of test tools that might be used,the order in which modules are coded and tested, the cost of generating test cases, and the cost of debugging (locating and repairingdetected errors).
In short, then, it is a consideration of substantialimportance. In this section, two approaches, incremental and nonincremental testing, are discussed. In the next section, two incrementalapproaches, top-down and bottom-up development or testing, areexplored.The question pondered here is the following: Should you test aprogram by testing each module independently and then combiningthe modules to form the program, or should you combine the nextmodule to be tested with the set of previously tested modules beforeit is tested? The first approach is called nonincremental or “big-bang”testing or integration; the second approach is known as incrementaltesting or integration.The program in Figure 5.7 is used as an example.
The rectanglesrepresent the six modules (subroutines or procedures) in the program.The lines connecting the modules represent the control hierarchy ofthe program; that is, module A calls modules B, C, and D; module B106The Art of Software TestingFigure 5.7Sample six-module program.calls module E; and so on.
Nonincremental testing, the traditionalapproach, is performed in the following manner. First, a module testis performed on each of the six modules, testing each module as astand-alone entity. The modules might be tested at the same time orin succession, depending on the environment (e.g., interactive versusbatch-processing computing facilities) and the number of peopleinvolved. Finally, the modules are combined or integrated (e.g., “linkedited”) to form the program.The testing of each module requires a special driver module andone or more stub modules. For instance, to test module B, test cases arefirst designed and then fed to module B by passing it input argumentsfrom a driver module, a small module that must be coded to “drive,”or transmit, test cases through the module under test.
(Alternatively,a test tool could be used.) The driver module must also display, to thetester, the results produced by B. In addition, since module B callsmodule E, something must be present to receive control when B callsE. A stub module, a special module given the name “E” that must becoded to simulate the function of module E, accomplishes this.Module (Unit) Testing107When the module testing of all six modules has been completed, themodules are combined to form the program.The alternative approach is incremental testing.
Rather than testing each module in isolation, the next module to be tested is firstcombined with the set of modules that have already been tested.It is premature to give a procedure for incrementally testing theprogram in Figure 5.7, because there are a large number of possibleincremental approaches. A key issue is whether we should begin atthe top or bottom of the program. However, since this issue is discussed in the next section, let us assume for the moment that we arebeginning from the bottom.
The first step is to test modules E, C,and F, either in parallel (by three people) or serially. Notice that wemust prepare a driver for each module, but not a stub. The next stepis the testing of B and D, but rather than testing them in isolation,they are combined with modules E and F, respectively. In otherwords, to test module B, a driver is written, incorporating the testcases, and the pair B-E is tested.
The incremental process, adding thenext module to the set or subset of previously tested modules, is continued until the last module (Module A in this case) is tested. Notethat this procedure could have alternatively progressed from the topto the bottom.Several observations should be apparent at this point.1. Nonincremental testing requires more work. For the program in Figure 5.7, five drivers and five stubs must be prepared (assuming we do not need a driver module for the topmodule).
The bottom-up incremental test would require fivedrivers but no stubs. A top-down incremental test wouldrequire five stubs but no drivers. Less work is requiredbecause previously tested modules are used instead of thedriver modules (if you start from the top) or stub modules(if you start from the bottom) needed in the nonincrementalapproach.2.
Programming errors related to mismatching interfaces orincorrect assumptions among modules will be detected earlier if incremental testing is used. The reason is that combina-108The Art of Software Testingtions of modules are tested together at an early point in time.However, if nonincremental testing is used, modules do not“see one another” until the end of the process.3.
As a result, debugging should be easier if incremental testingis used. If we assume that errors related to intermodule interfaces and assumptions do exist (a good assumption fromexperience), then, if nonincremental testing has been used,the errors will not surface until the entire program has beencombined. At this time, we may have difficulty pinpointingthe error, since it could be anywhere within the program.Conversely, if incremental testing is used, an error of thistype should be easier to pinpoint, because it is likely that theerror is associated with the most recently added module.4. Incremental testing might result in more thorough testing.
Ifyou are testing module B, either module E or A (dependingon whether you started from the bottom or the top) is executed as a result. Although E or A should have been thoroughly tested previously, perhaps executing it as a result ofB’s module test will evoke a new condition, perhaps one thatrepresents a deficiency in the original test of E or A. On theother hand, if nonincremental testing is used, the testing of Bwill affect only module B. In other words, incremental testing substitutes previously tested modules for the stubs ordrivers needed in the nonincremental test.
As a result, theactual modules receive more exposure by the completion ofthe last module test.5. The nonincremental approach appears to use less machinetime. If module A of Figure 5.7 is being tested using thebottom-up approach, modules B, C, D, E, and F probablyexecute during the execution of A. In a nonincremental testof A, only stubs for B, C, and E are executed. The same istrue for a top-down incremental test.
If module F is beingtested, modules A, B, C, D, and E may be executed duringthe test of F; in the nonincremental test of F, only the driverfor F, plus F itself, executes. Hence, the number of machineinstructions executed during a test run using the incrementalModule (Unit) Testing109approach is apparently greater than that for the nonincremental approach. However, offsetting this is the fact that thenonincremental test requires more drivers and stubs than theincremental test; machine time is needed to develop the drivers and stubs.6.
At the beginning of the module-testing phase, there is moreopportunity for parallel activities if nonincremental testing isused (that is, all the modules can be tested simultaneously).This might be of significance in a large project (many modules and people), since the head count of a project is usuallyat its peak at the start of the module-test phase.In summary, observations 1 through 4 are advantages of incremental testing, and observations 5 through 6 are disadvantages. Givencurrent trends in the computing industry (hardware costs have beendecreasing and seem destined to continue to do so while hardwarecapability increases, and labor costs and the consequences of softwareerrors are increasing), and given the fact that the earlier an error isfound, the lower the cost of repairing it, you can see that observations 1 through 4 are increasing in importance while observation 5 isbecoming less important.
Observation 6 seems to be a weak disadvantage, if one at all. This leads to the conclusion that incrementaltesting is superior.Top-down versus Bottom-up TestingGiven the conclusion of the previous section—that incremental testing is superior to nonincremental testing—two incremental strategiesare explored: top-down and bottom-up testing. Before discussingthem, however, several misconceptions should be clarified.