Nothing Special   »   [go: up one dir, main page]

Academia.eduAcademia.edu

Testing: principles and practice

1996, ACM Computing Surveys

Testing: Principles and Practice STEPHEN R. SCHACH Department of Computer Science, Vanderbilt University, Nashville, TN ^srs@vuse.vanderbilt.edu& Testing is the process of determining whether a task has been correctly carried out. Testing should be performed throughout the software life cycle; it should not be restricted to verification (testing whether a phase has been carried out correctly) and validation (testing whether the completed product satisfies its specifications). The correction of a fault exposed by testing is termed debugging. The goal of testing is to reveal faults. There are two types of testing: execution-based testing and nonexecutionbased testing. It is impossible to execute a specification document; instead, it has to be reviewed carefully. Once executable code has been written it is possible to run test cases, that is, perform execution-based testing. Nevertheless, the existence of code does not preclude nonexecution-based testing because carefully reviewing code will uncover at least as many faults as running test cases. In this survey, the principles and practice of both execution-based and nonexecution-based testing are described. NONEXECUTION-BASED TESTING The principle underlying nonexecutionbased testing techniques such as walkthroughs and inspections is that a review by a team of experts with a broad range of expertise increases the chance of finding a fault. Nonexecution-based testing is remarkably effective. At the Jet Propulsion Laboratory (JPL), on average each two-hour inspection exposed four major and fourteen minor faults [Bush 1990], resulting in a saving of approximately $25,000 per inspection. Another JPL study [Kelly et al. 1992] shows that the number of faults detected decreases exponentially by phase. In other words, inspections result in faults being detected early in the software process, thereby saving both time and money. The Cleanroom software development approach incorporates a number of different techniques, including an incremental life-cycle model, formal techniques for specification and design, and nonexecution-based module-testing techniques such as code reading and code inspections [Dyer 1992]. A critical aspect of the technique is that a module is not compiled until it has passed an inspection. As reported in Linger [1994], seventeen products totaling nearly one million lines of code were developed using Cleanroom. These included the 350,000-line Ericsson Telecom OS32 operating system. Overall, the weighted average testing fault rate was only 2.3 faults per KLOC. An alternative nonexecution-based technique is correctness proving. This consists of using a mathematical proof to show that a product is correct, that is, satisfies its specifications. Dijkstra [1972] has stated that “the only effective way to raise the confidence level of a program significantly is to give a convincing proof of its correctness.” However, even if a product is proved correct, it must nevertheless be subjected to thorough execution-based testing [Schach 1996, Section 5.5.2]. Despite some problems with correctness proving, proofs are appropriate where indicated by risk or cost-benefit Copyright © 1996, CRC Press. ACM Computing Surveys, Vol. 28, No. 1, March 1996 278 • Stephen R. Schach analysis, and when human lives are at stake. Even when a full formal proof is not justified, the quality of software can be markedly improved through the use of informal proofs and by inserting assertions into the code. EXECUTION-BASED TESTING We need to test a number of different aspects of a software product, including its utility, reliability, robustness, performance, and correctness. There are two basic ways of systematically constructing test data to test the correctness of a module. The first is testing to specifications (or black-box testing). In this approach, the code is ignored; the only information used in drawing up test cases is the specification document. The other extreme is testing to code (or glass-box testing) where the test cases are based solely on the code. Neither approach is feasible because of the combinatorial explosion; there are simply too many test cases to consider. The goal of execution-based testing is therefore to highlight as many faults as possible while accepting that there is no way to guarantee that all faults have been detected [Myers 1979; Beizer 1990]. A reasonable way to proceed is first to use black-box test cases (testing to specifications) and then to develop additional test cases using glass-box techniques (testing to code). The art of black-box testing is to use the specifications to devise a small, manageable set of test cases to maximize the chances of detecting a previously undetected fault while minimizing the chances of wasting a test case by having the same fault detected by more than one test case. The favored technique for achieving this is equivalence testing combined with boundary-value analysis [Schach 1996, Section 12.15.1]. There are a number of different forms of glass-box testing, including statement, branch, and path coverage. The most powerful form of structural testing is path coverage, that is, testing all possible paths. However, in a product with ACM Computing Surveys, Vol. 28, No. 1, March 1996 loops the number of paths can be huge. In practice, therefore, techniques are used that reduce the number of paths to be examined while still being able to uncover more faults than would be possible using less comprehensive structural testing methods. One example is all-definition-use-path coverage. In this technique, each occurrence of a variable in the source code is labeled either as a definition of the variable or as a use of the variable. Next, all paths between the definition of a variable and the use of that definition are identified, nowadays by means of a CASE tool. Finally, a test case is set up for each such path. All-definition-use-path coverage is favored because large numbers of faults can frequently be detected using relatively few test cases [Schach 1996, Section 12.16.1]. FUTURE PROSPECTS Software is tested in order to detect faults. However, instead of using better techniques for detecting faults, it is more effective to employ software-development approaches (such as Cleanroom) that reduce the number of faults in the software. Thus, the future role of testing will be to prevent faults rather than to detect them. ACKNOWLEDGMENT This survey was based on material taken from Stephen R. Schach, Classical and Object-Oriented Software Engineering, Third Edition, Richard D. Irwin Inc., 1996, pages 109–133 and 405–420. REFERENCES BEIZER, B. 1990. Software Testing Techniques, 2nd ed. Van Nostrand Reinhold, New York. BUSH, M. 1990. Improving software quality: The use of formal inspections at the Jet Propulsion Laboratory. In Proceedings of the 12th International Conference on Software Engineering. (Nice, France), 196 –199. DIJKSTRA, E. W. 1972. The humble programmer. Commun. ACM 15, 10 (Oct.), 859 – 866. Testing: Principles and Practice DYER, M. 1992. The Cleanroom Approach to Quality Software Development. Wiley, New York. KELLY, J. C., SHERIF, J. S., AND HOPS, J. 1992. An analysis of defect densities found during software inspections. J. Syst. Softw. 17, 1 (Jan.), 111–117. • 279 LINGER, R. C. 1994. Cleanroom process model. IEEE Software 11, 3 (Mar.), 50 –58. MYERS, G. 1979. The Art of Software Testing. Wiley, New York. SCHACH, S. R. 1996. Classical and Object-Oriented Software Engineering, 3rd ed. Richard D. Irwin, Inc., Chicago, IL. ACM Computing Surveys, Vol. 28, No. 1, March 1996