Every Thing About Testing
snap from the Book "The Art of Software Testing" 2012
The below list, 15 categories of test cases, along with a brief description
We discuss the categories in turn here. We don’t claim that all 15 categories apply to every program, but to avoid overlooking something, we recommend that you explore all of them when designing test cases.
- Facility Ensure that the functionality in the objectives is implemented.
- Volume Subject the program to abnormally large volumes of data to process.
- Stress Subject the program to abnormally large loads, generally concurrent processing.
- Usability Determine how well the end user can interact with the program.
- Security Try to subvert the program’s security measures.
- Performance Determine whether the program meets response and throughput requirements.
- Storage Ensure the program correctly manages its storage needs, both system and physical.
- Configuration Check that the program performs adequately on the recommended configurations.
- Compatibility / Conversion Determine whether new versions of the program are compatible with previous releases.
- Installation Ensure the installation methods work on all supported platforms.
- Reliability Determine whether the program meets reliability specifications such as up-time and MTBF.
- Recovery Test whether the system’s recovery facilities work as designed.
- Serviceability / Maintenance Determine whether the application correctly provides mechanisms to yield data on events requiring technical support.
- Documentation Validate the accuracy of all user documentation.
- Procedure Determine the accuracy of special procedures required to use or maintain the program.
Facility Testing
The most obvious type of system testing is to determine whether each facility (or function; but the word ‘‘function’’ is not used here to avoid confusing this with function testing) mentioned in the objectives was actually implemented. The procedure is to scan the objectives sentence by sentence, and when a sentence specifies a what (e.g., ‘‘syntax should be consistent . . . ,’’ ‘‘user should be able to specify a range of locations . . .’’), determine that the program satisfies the ‘‘what.’’ This type of testing often can be performed without a computer; a mental comparison of the objectives with the user documentation is sometimes sufficient. Nonetheless, a checklist is helpful to ensure that you mentally verify the same objectives the next time you perform the test.
Volume Testing
A second type of system testing is to subject the program to heavy volumes of data. For instance, a compiler could be fed an absurdly large source program to compile. A linkage editor might be fed a program containing thousands of modules. An electronic circuit simulator could be given a circuit containing millions of components. An operating system’s job queue might be filled to capacity. If a program is supposed to handle files spanning multiple volumes, enough data is created to cause the program to switch from one volume to another. In other words, the purpose of volume testing is to show that the program cannot handle the volume of data specified in its objectives.
Obviously, volume testing can require significant resources, therefore, in terms of machine and people time, you shouldn’t go overboard. Still, every program must be exposed to at least a few volume tests.
Stress Testing
Stress testing subjects the program to heavy loads, or stresses. This should not be confused with volume testing; a heavy stress is a peak volume of data, or activity, encountered over a short span of time. An analogy would be evaluating a typist: A volume test would determine whether the typist could cope with a draft of a large report; a stress test would determine whether the typist could type at a rate of 50 words per minute.
Because stress testing involves an element of time, it is not applicable to many programs—for example, a compiler or a batch-processing payroll program. It is applicable, however, to programs that operate under varying loads, or interactive, real-time, and process control programs. If an air traffic control system is supposed to keep track of up to 200 planes in its sector, you could stress-test it by simulating the presence of 200 planes. Since there is nothing to physically keep a 201st plane from entering the sector, a further stress test would explore the system’s reaction to this unexpected plane. An additional stress test might simulate the simultaneous entry of a large number of planes into the sector.
If an operating system is supposed to support a maximum of 15 concurrent jobs, the system could be stressed by attempting to run 15 jobs simultaneously. You could stress a pilot training aircraft simulator by determining the system’s reaction to a trainee who forces the rudder left, pulls back on the throttle, lowers the flaps, lifts the nose, lowers the landing gear, turns on the landing lights, and banks left, all at the same time. (Such test cases might require a four-handed pilot or, realistically, two test specialists in the cockpit.) You might stress-test a process control system by causing all of the monitored processes to generate signals simultaneously, or a telephone switching system by outing to it a large number of simultaneous phone calls.
Web-based applications are common subjects of stress testing. Here, you want to ensure that your application, and hardware, can handle a target volume of concurrent users. You could argue that you may have millions of people accessing the site at one time, but that is not realistic. You need to define your audience then design a stress test to represent the maximum number of users you think will use your site.
Similarly, you could stress a mobile device application—a mobile phone operating system, for example—by launching multiple applications that run and stay resident, then making or receiving one or more telephone calls. You could launch a GPS navigation program, an application that uses CPU and radio frequency (RF) resources almost continuously, then attempt to use other applications or engage telephone calls. Although many stress tests do represent conditions that the program likely will experience during its operation, others may truly represent ‘‘never will occur’’ situations; but this does not imply that these tests are not useful. If these impossible conditions detect errors, the test is valuable because it is likely that the same errors might also occur in realistic, less stressful situations.
Usability Testing
Another important test case area is usability, or user testing. Although this testing technique is nearly 30 years old, it has become more important with the advent of more GUI-based software and the deep penetration of computer hardware and software into all aspects of our society. By tasking the ultimate end user of an application with testing the software in a real-world environment, potential problems can be discovered that even the most aggressive automated testing routing likely wouldn’t find.
Security Testing
In response to society’s growing concern about privacy, many programs now have specific security objectives. Security testing is the process of attempting to devise test cases that subvert the program’s security checks. For example, you could try to formulate test cases that get around an operating system’s memory protection mechanism. Similarly, you could try to subvert a database system’s data security mechanisms. One way to devise such test cases is to study known security problems in similar systems and generate test cases that attempt to demonstrate comparable problems in the system you are testing. For example, published sources in magazines, chat rooms, or newsgroups frequently cover known bugs in operating systems or other software systems. By searching for security holes in existing programs that provide services similar to the one you are testing, you can devise test cases to determine whether your program suffers from the same kind of problems.
Web-based applications often need a higher level of security testing than do most applications. This is especially true of e-commerce sites. Although sufficient technology, namely encryption, exists to allow customers to complete transactions securely over the Internet, you should not rely on the mere application of technology to ensure safety. In addition, you will need to convince your customer base that your application is safe, or you risk losing customers.
Performance Testing
Many programs have specific performance or efficiency objectives, stating such properties as response times and throughput rates under certain workload and configuration conditions. Again, since the purpose of a system test is to demonstrate that the program does not meet its objectives, test cases must be designed to show that the program does not satisfy its performance objectives.
Storage Testing
Similarly, programs occasionally have storage objectives that state, for example, the amount of system memory the program uses and the size of temporary or log files. You need to verify that your program can control its use of system memory so it does not negatively impact other processes running on the host. The same holds for physical files on the file system. Filling a disk drive can cause significant downtime. You should design test cases to show that these storage objectives have not been met.
Configuration Testing
Programs such as operating systems, database management systems, and messaging programs support a variety of hardware configurations, including various types and numbers of I/O devices and communications lines, or different memory sizes. Often, the number of possible configurations is too large to test each one, but at the least, you should test the program with each type of hardware device and with the minimum and maximum configuration. If the program itself can be configured to omit program components, or if the program can run on different computers, each possible configuration of the program should be tested. Today, many programs are designed for multiple operating systems. Thus, when testing such a program, you should do so on all of the operating systems for which it was designed. Programs designed to execute within a Web browser require special attention, since there are numerous Web browsers available and they don’t all function the same way. In addition, the same Web browser will operate differently on different operating systems.
Compatibility/Conversion Testing
Most programs that are developed are not completely new; they often are replacements for some deficient system. As such, programs often have specific objectives concerning their compatibility with, and conversion procedures from, the existing system. Again, in testing the program against these objectives, the orientation of the test cases is to demonstrate that the compatibility objectives have not been met and that the conversion procedures do not work. Here you try to generate errors while moving data from one system to another. An example would be upgrading a database system. You want to ensure that the new release supports your existing data, just as you need to validate that a new version of a word processing application supports its previous document formats. Various methods exist to test this process; however, they are highly dependent on the database system you employ.
Installation Testing
Some types of software systems have complicated installation procedures. Testing the installation procedure is an important part of the system testing process. This is particularly true of an automated installation system that is part of the program package. A malfunctioning installation program could prevent the user from ever having a successful experience with the main system you are testing. A user’s first experience is when he or she installs the application. If this phase performs poorly, then the user/customer may find another product, or have little confidence in the application’s validity.
Reliability Testing
Of course, the goal of all types of testing is the improvement of the program reliability, but if the program’s objectives contain specific statements about reliability, specific reliability tests might be devised. Testing reliability objectives can be difficult. For example, a modern online system such as a corporate wide area network (WAN) or an Internet service provider (ISP) generally has a targeted up-time of 99.97 percent over the life of the system. There is no known way that you could test this objective within a test period of months or even years. Today’s critical software systems have even higher reliability standards, and today’s hardware conceivably should support these objectives. You potentially can test programs or systems with more modest mean time between failures (MTBF) objectives or reasonable (in terms of testing) operational error objectives.
An MTBF of no more than 20 hours, or an objective that a program should experience no more than 12 unique errors after it is placed into production, for example, presents testing possibilities, particularly for statistical, program-proving, or model-based testing methodologies. For example, if this area of program testing is of interest to you, research the concept of inductive assertions.
As complex as this sort of software proving or prediction sounds, reliability testing and, indeed, the concept of software reliability engineering (SRE) are with us today and are increasingly important for systems that must maintain very high up-times.
Recovery Testing
Programs such as operating systems, database management systems, and teleprocessing programs often have recovery objectives that state how the system is to recover from programming errors, hardware failures, and data errors. One objective of the system test is to show that these recovery functions do not work correctly. Programming errors can be purposely injected into a system to determine whether it can recover from them. Hardware failures such as memory parity errors or I/O device errors can be simulated. Data errors such as noise on a communications line or an invalid pointer in a database can be created purposely or simulated to analyze the system’s reaction.
One design goal of such systems is to minimize the mean time to recovery (MTTR). Downtime often causes a company to lose revenue because the system is inoperable. One testing objective is to show that the system fails to meet the service-level agreement for MTTR. Often, the MTTR will have an upper and lower boundary, so your test cases should reflect these bounds.
Serviceability/Maintenance Testing
The program also may have objectives for its serviceability or maintainability characteristics. All objectives of this sort must be tested. Such objectives might define the service aids to be provided with the system, including storage dump programs or diagnostics, the mean time to debug an apparent problem, the maintenance procedures, and the quality of internal logic documentation.
Documentation Testing
As we illustrated in Figure 6.4, the system test also is concerned with the accuracy of the user documentation. The principal way of accomplishing this test is to use the documentation to determine the representation of the prior system test cases. That is, once a particular stress case is devised, you would use the documentation as a guide for writing the actual test case. Also, the user documentation itself should be the subject of an inspection, to check it for accuracy and clarity. Any examples illustrated in the documentation should be encoded into test cases and fed to the program.
Procedure Testing
Finally, many programs are parts of larger, not completely automated systems involving procedures people perform. Any prescribed human procedures, such as those for the system operator, database administrator, or end user, should be tested during the system test. For example, a database administrator should document procedures for backing up and recovering the database system. If possible, a person not associated with the administration of the database should test the procedures. However, a company must create the resources needed to adequately test the procedures. These resources often include hardware and additional software licensing.
Function Testing
As indicated in Figure 6.3 ( below ) , function testing is a process of attempting to find discrepancies between the program and the external specification. An external specification is a precise description of the program’s behavior from the end-user point of view.
Except when used on small programs, function testing is normally a black-box activity. That is, you rely on the earlier module-testing process to achieve the desired white-box logic coverage criteria.
To perform a function test, you analyze the specification to derive a set of test cases. The equivalence partitioning, boundary value analysis, cause-effect graphing, and error-guessing methods described in Chapter 4 are especially pertinent to function testing. In fact, the examples in Chapter 4 are examples of function tests. The descriptions of the Fortran DIMENSION statement, the examination scoring program, and the DISPLAY command actually are examples of external specifications. They are not, however, completely realistic examples; for instance, an actual external specification for the scoring program would include a precise description of the format of the reports. (Note: Since we discussed function testing in Chapter 4, we present no examples of function tests in this section.)
Many of the guidelines we provided in Chapter 2 also are particularly pertinent to function testing. In particular, keep track of which functions have exhibited the greatest number of errors; this information is valuable because it tells you that these functions probably also contain the preponderance of as-yet undetected errors. Also, remember to focus a sufficient amount of attention on invalid and unexpected input conditions. (Recall that the definition of the expected result is a vital part of a test case.)
Finally, as always, keep in mind that the purpose of the function test is to expose errors and discrepancies with the specification, not to demonstrate that the program matches its external specification.
FIGURE 6.3 The Correspondence Between Development and Testing Processes.
System Testing
System testing is the most misunderstood and most difficult testing process. System testing is not a process of testing the functions of the complete system or program, because this would be redundant with the process of function testing. Rather, as shown in Figure 6.3, system testing has a
particular purpose: to compare the system or program to its original objectives. Given this purpose, consider these two implications:
1. System testing is not limited to systems. If the product is a program, system testing is the process of attempting to demonstrate how the program, as a whole, fails to meet its objectives.
2. System testing, by definition, is impossible if there is no set of written, measurable objectives for the product.
In looking for discrepancies between the program and its objectives, focus on translation errors made during the process of designing the external specification. This makes the system test a vital test process, because in terms of the product, the number of errors made, and the severity of those errors, this step in the development cycle usually is the most error prone. It also implies that, unlike the function test, the external specification cannot be used as the basis for deriving the system test cases, since this would subvert the purpose of the system test. On the other hand, the objectives document cannot be used by itself to formulate test cases, since it does not, by definition, contain precise descriptions of the program’s external interfaces. We solve this dilemma by using the program’s user
documentation or publications—design the system test by analyzing the objectives; formulate test cases by analyzing the user documentation. This has the useful side effect of comparing the program to its objectives and to the user documentation, as well as comparing the user documentation to
the objectives, as shown in Figure 6.4.
Figure 6.4 illustrates why system testing is the most difficult testing process. The leftmost arrow in the figure, comparing the program to its objectives, is the central purpose of the system test, but there are no known test case design methodologies. The reason for this is that objectives state what a program should do and how well the program should do it, but they do not state the representation of the program’s functions. For instance, the objectives for the DISPLAY command specified in Chapter 4 might have read as follows:
A command will be provided to view, from a terminal, the contents of main storage locations. Its syntax should be consistent with the syntax of all other system commands. The user should be able to specify a range of locations, via an address range or an address and a count.
Sensible defaults should be provided for command operands.
Output should be displayed as multiple lines of multiple words (in hexadecimal), with spacing between the words. Each line should contain the address of the first word of that line. The command is a
‘‘trivial’’ command, meaning that under reasonable system loads, it should begin displaying output within two seconds, and there should be no observable delay time between output lines. A programming error in the command processor should, at the worst, cause the com-
mand to fail; the system and the user’s session must not be affected.
The command processor should have no more than one user detected error after the system is put into production.
Given the statement of objectives, there is no identifiable methodology that would yield a set of test cases, other than the vague but useful guideline of writing test cases to attempt to show that the program is inconsistent with each sentence in the objectives statement. Hence, a different approach to test-case design is taken here: Rather than describing a methodology, distinct categories of system test cases are discussed. Because of the absence of a methodology, system testing requires a substantial amount of creativity; in fact, the design of good system test cases requires more creativity, intelligence, and experience than are required to design the system or program itself.
Table 6.1 lists 15 categories of test cases, along with a brief description. We discuss the categories in turn here. We don’t claim that all 15 categories apply to every program, but to avoid overlooking something, we recommend that you explore all of them when designing test cases.
TABLE 6.1 15 Categories of Test Cases
Category Description
Facility Ensure that the functionality in the objectives is implemented.
Volume Subject the program to abnormally large volumes of data to process.
Stress Subject the program to abnormally large loads, generally concurrent processing.
Usability Determine how well the end user can interact with the program.
Security Try to subvert the program’s security measures.
Performance Determine whether the program meets response and throughput requirements.
Storage Ensure the program correctly manages its storage needs, both system and physical.
Configuration Check that the program performs adequately on the recommended configurations.
Installation Ensure the installation methods work on all supported platforms.
Reliability Determine whether the program meets reliability specifications such as uptime and MTBF.
Recovery Test whether the system’s recovery facilities work as designed.
Procedure Determine the accuracy of special procedures required to use or maintain the program.
Documentation Validate the accuracy of all user documentation.
Compatibility/Conversion Determine whether new versions of the program are compatible with previous releases.
Serviceability/ Maintenance Determine whether the application correctly provides mechanisms to yield data on events requiring technical support.
The real definition of sw development “done” is not when development is done coding. Instead, code is only “done” when it has been fully tested and is operating in production as designed.