![]() |
Yuhang (Henry) Wang Scott Thornton |
2.0 Testing Fundamentals |
|---|
| Table of Contents | |
As the name suggests, the Software Testing includes the running of a series of dynamic executions of the software product. For a test to be a test (sometimes called a test case) it must have the following properties:
Tests are run to assess the level of quality in a software product. They determine what a system actually does, and to what level of performance. As well, testing helps to achieve software quality by finding defects, along with other activities in the software development process. Finally testing helps to preserve quality by enabling a modified system to be retested, ensuring that what worked before still works. Glen Myers [Myers 1979] states that
By uncovering errors in the software, their cause can be determined and then a fix implemented. This results in a software product that contains fewer defects, achieving a greater level of quality. Additional tests may or may not uncover errors, which leads to the fundamental limitation of testing. Testing can only show the presence of a defect. It can never prove the absence of all errors. As is well known, producing error free software is extremely difficult. The developer requires an assessment of the quality of the software before releasing it to customers. This assessment is derived from testing. If no or few errors are found, then the quality of the software is assumed good, providing some confidence that the product is working well. Therefore, from this it can be seen that software testing has two main objectives:
It is interesting to note that the two testing objectives result in what is known as the "Testing Paradox". If the first objective is to uncover errors in the software product, how can there be confidence that the product is working well, since it was just proved that it is, in fact is not working! It must also be noted that test cases that pass (i.e. produce the expected results) do not, in and of themselves, improve the quality of the software product. Nothing has changed in the software under test, so given that there is no change there can be no improvement or degradation. Rather, these tests only improve our confidence in the software product.
|
|
Overall testing of a software system can be divided into essentially four levels or stages. Each stage parallels the level of complexity found within a software product during development.
At the lowest and simplest level is Unit Testing. Here, the basic units of the software are tested in isolation. (A unit is defined to be the smallest testable piece of software [Beizer 1990].) The objectives are to find errors in these units in either the logic or data. Units are assembled into larger aggregates called components. When two or more tested components or units are combined, the testing done on the aggregate is called Component Integration Testing, or just Integration Testing. The tests done at this level look for errors in the interfaces between the components. As well, the functions, which can now be performed by the aggregate, that were not testable individually must also be examined. After the all the components have been assembled, the entire system can be tested as a whole, and as such this is called System Testing. It might be argued that "System Testing" is just the final stage of component integration testing. However, at this stage the functional and/or requirements specification is used to generate the test cases. System Testing looks for errors in the end to end functionality of the system as well as errors in the non-functional requirements such as performance, reliability, and security. The last stage of testing is Validation or Acceptance Testing. Here the system is handed over to the end-user or customers. The purpose of this testing is to give confidence that the system is ready for operational use, rather than to find errors. Thus, this is more correctly called a demonstration rather than a test. Each level of testing addresses different views of the quality of the software product as shown in Table 1.
Table 1 Testing Levels verus Quality Views
A "Verification and Validation" software life cycle model is usually used to demonstrate the goals of the different testing stages. In this model, Verification and Validation is used to refer the testing activities. Verification is the actions in the testing that ensure a specification or function is correctly implemented. The activities that ensure the software that has been built is traceable to the original requirement specification are known as Validation. Boehm [Boehm 1981] states this in two simple sentences: Verification: "Are we building the product right?". Validation: "Are we building the right product?"
Figure 1 Verification and Validation Software Lifecycle Model |
|
Software Testing Techniques provide systematic approaches for designing tests that exercise the internal logic of software components and the input and output domains of the program to uncover errors in
program functions, behaviours and performances. Therefore, testing techniques are not only performed on the functional areas but also non-functional areas of the software. The next few sections will examine several types of testing techniques.
|
|
|
The primary difference between static and dynamic testing is that static techniques don not exercise the software in its execution environment. On the other hand, dynamic testing involves the operation of the software with a set of test inputs, and results in a test output.
Static analysis testing developed from compiler technology, resulting in a significant number of errors being uncovered. This analysis can examine the control and data flow, check for dead or unreachable code, and identify infinite loops, uninitialized or unused variables, and standards violations. Certain measures such as McCabe s Cyclomatic Complexity are calculated statically and provide an assessment of the testability of the software entity. Dynamic test techniques can be classified into Functional or Structural techniques. These are often referred to as Black Box or White (Glass) Box testing, respectively, and are described in the next section.
|
|
Black-box tests are executed to validate the functional requirements without analysis of the internal logic of the program. In other words, the tester does not consider the how a software component performs its function, but rather just that it does. The ideal black-box tests are executed based on a set of test cases that satisfy the following criteria [Myers 1979]:
The goal of black box testing is to find errors such as
White box tests are executed to verify whether the program is running correctly by considering the internal logical structure. Test items are chosen to exercise the required parts of the structure. The test cases designed for performing white box testing should follow the following criteria:
One concrete white box testing technique is "Basis Path Testing", as proposed by [McCabe 1976]. There are also other techniques, such as Condition Testing [Tai 1989], Data Flow Testing, and Loop testing. White box testing and black box testing are complementary techniques. Only using one of them is impractical in the real software testing world. They are typically combined to provide an approach that validates both the interface and the internal workings of the software.
|
|
|
Testing is more effective if the various tests are distributed over the complete range of possibilities rather than being drawn from just a few. Input values that are processed in an equivalent fashion can be regarded as being equivalent. If the input domain is then partitioned into equivalent subsets, then a good set of cases would draw an input value from each rather than concentrate on only a few of the subsets.
|
|
|
Boundary Value Analysis is related to equivalence partitioning. These values lie on the boundaries of an equivalence partition. As was suggested above, test cases should be drawn from each equivalence partition. Values on each side of a partition should also be tested, addressing one of the most common coding errors, that of being "off by one". It might be argued that since any value within a particular equivalence set is good as another, boundary testing is superfluous. It must be noted however that the equivalence partitions are defined by these boundary values.
Boundaries can exist on output data ranges as well. Tests should be designed to produce valid and (attempt to produce) invalid outputs. Hidden boundaries such as maximum string lengths or data set sizes also need to be determined and verified that appropriate responses are generated by the software under test.
|
|
|
A path is defined to be a sequence of program statements that are executed by the software under test in response to a specific input. In most software units, there is a potentially (near) infinite number of different paths through the code, so complete path coverage is impractical. Not withstanding that, a number of structural techniques that involve the paths through the code can lead to a reasonable test result.
|
|
|
Branch Testing
|
The structure of the software under test can be shown using a control flow diagram, illustrating statements and decision points. The number of unique paths from the start to the end of the code is equal to the number of decision points plus one. This number is just the Cyclomatic Complexity of the program [McCabe 1976]. Using the control flow diagram, test cases can be designed such that each exercises at least one new segment of the control flow graph. In theory the number of test cases required should be equal to the cyclomatic complexity, however in practice it is extremely difficult to do this operationally.
|
|
Condition Testing
|
In branch testing, only the value of the complete boolean expression at each decision point is taken into consideration, regardless if that expression is a simple one or is a compound expression. In Condition Testing, a test case is designed for each component of the boolean expression involved in a decision point.
|
|
There are many debates around the idea that software inspections at the code level can replace testing. Experience has shown them to be a powerful defect prevention methodology. It is often said that the best way to come to understand a topic is to have to teach or explain it to another. Inspections encourage just that philosophy. However, inspections are a static analysis of the software being examined. Given the complexity of software systems being developed today, it is unlikely that this static analysis will be capable of detecting defects that involve significant interactions between multiple components, or be able to assess its performance characteristics. The Such assessments can only be determined from a dynamic form of testing.
These leads to the potential conclusion that inspections may effectively address the software quality issues at the unit test and some portion of the integration test levels. However, as the complexity of the system under test increases, there is a threshold where static analysis must give way to the dynamic nature of testing. In other words, inspections and testing are complementary techniques to assess or improve the quality of the software product. Each should be employed where its return on investment is greatest, or where the alternate technique is incapable of being completely successful.
|
![]() |
||||
Scott Thornton
Last Modified Date: 10-April-2003 |
|
|||