Software Engineering for Students A Programming Approach

Software Engineering for Students A Programming Approach Software Engineering for Students A Programming Approach

web.firat.edu.tr
from web.firat.edu.tr More from this publisher
21.08.2013 Views

Figure 19.2 Unit testing Driver Component under test 19.8 System (integration) testing 277 Thus the component under test is surrounded by scaffolding. This is a large undertaking. In many developments, the collections of drivers and stubs is often as big as the software itself. 19.8 ● System (integration) testing Thus far we have only considered unit testing – testing an individual software component, a method or a class. We have implicitly assumed that such a component is fairly small. This is the first step in the verification of software systems, which typically consist of tens or hundreds of individual components. The task of testing complete systems is called system or integration testing. Suppose that we have designed and code all the components for a system. How can we test these components and how can we test the complete system? Here are three different approaches to system testing: 1. big bang – bring all the components together, without prior testing, and test the complete system 2. improved big bang – test each component individually (unit testing), bring them all together and test the complete system 3. incremental – build the system piece by piece, testing the partial system at each stage. The first approach – big bang or monolithic testing – is a recipe for disaster. There is no easy way of knowing which component is the cause of a fault, and there is an enormous debugging task. The second approach is slightly better because when the components are brought together, we have some confidence in them individually. Now any faults are likely to be caused by the interactions between the components. Here again, there is a major problem of locating faults. An alternative is to use some form of incremental testing. In this approach, first one component of the system is tested, then a second component is linked with the first and the system tested. Any fault is likely to be localized either in the newly incorporated component or in the interface between the two. We continue like this, adding just one component at a time. At each stage, any fault that presents itself is likely to be caused by the new component, or by its interface to the system. Thus fault finding is Stub Stub Stub

278 Chapter 19 ■ Testing made considerably easier. Various approaches are explained in Chapter 24 on incremental development. 19.9 ● Discussion We have seen that exhaustive testing is infeasible. Therefore complete testing is impossible and, whatever testing methods are used, they can never ensure that the software is free from bugs. Thus testing is a poor technique but until formal verification becomes widely applicable it is a vital technique. However much we test our programs, using all our skill and intuition, we can never be sure that we have eradicated all the faults. The situation is well summed up by one of computing’s gurus, Dijkstra, in his famous remark, “Testing can only show the presence of bugs, never their absence.” This has been (anonymously) rephrased as, “Just because you have never seen a mermaid doesn’t mean that they don’t exist.” It can be reassuring to adopt the view that a test that reveals no bugs is a successful test. But rather we should look upon such a test as unsuccessful! It is difficult to get accurate data on the number of bugs present in production software because, unsurprisingly, organizations do not want to reveal this kind of information. The indications are that there are typically between 2 and 50 bugs per 1,000 lines of source code in commercial production software. A figure like this is more properly called a fault density. It measures the number of known faults per 1,000 lines of code (LOC). A figure of 2 is considered to be most creditable. Ways of measuring this quantity are explained in Chapter 29 on metrics and quality assurance. The trouble is, of course, that bugs always surface at the worst possible time, for example, when you are demonstrating the completed software to the client. This phenomenon has long been known to students of reliability, who quote Murphy’s laws: 1. “If a system can fail, it will,” 2. “and at the worst possible moment.” Another, more objective, observation is that some bugs create serious faults, while others lie dormant and do not give any trouble. Chapter 31 on assessing methods looks at the evidence that is available to compare verification techniques, including testing. The surprising indications are that simply inspecting code is more effective than carrying out testing. The worrying conclusion to any discussion of verification is that all software (of any significant size) contains faults. Summary Testing is one set of techniques for verifying software. Exhaustive testing is a practical impossibility.

Figure 19.2 Unit testing<br />

Driver<br />

Component<br />

under test<br />

19.8 System (integration) testing 277<br />

Thus the component under test is surrounded by scaffolding. This is a large undertaking.<br />

In many developments, the collections of drivers and stubs is often as big as the<br />

software itself.<br />

19.8 ● System (integration) testing<br />

Thus far we have only considered unit testing – testing an individual software component,<br />

a method or a class. We have implicitly assumed that such a component is fairly<br />

small. This is the first step in the verification of software systems, which typically consist<br />

of tens or hundreds of individual components. The task of testing complete systems<br />

is called system or integration testing.<br />

Suppose that we have designed and code all the components <strong>for</strong> a system. How can<br />

we test these components and how can we test the complete system?<br />

Here are three different approaches to system testing:<br />

1. big bang – bring all the components together, without prior testing, and test the<br />

complete system<br />

2. improved big bang – test each component individually (unit testing), bring them<br />

all together and test the complete system<br />

3. incremental – build the system piece by piece, testing the partial system at each<br />

stage.<br />

The first approach – big bang or monolithic testing – is a recipe <strong>for</strong> disaster. There is<br />

no easy way of knowing which component is the cause of a fault, and there is an enormous<br />

debugging task. The second approach is slightly better because when the components<br />

are brought together, we have some confidence in them individually. Now any<br />

faults are likely to be caused by the interactions between the components. Here again,<br />

there is a major problem of locating faults.<br />

An alternative is to use some <strong>for</strong>m of incremental testing. In this approach, first one<br />

component of the system is tested, then a second component is linked with the first<br />

and the system tested. Any fault is likely to be localized either in the newly incorporated<br />

component or in the interface between the two. We continue like this, adding<br />

just one component at a time. At each stage, any fault that presents itself is likely to be<br />

caused by the new component, or by its interface to the system. Thus fault finding is<br />

Stub<br />

Stub<br />

Stub

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!