ST Module4 Notes
ST Module4 Notes
ST Module4 Notes
VI Semester
2021 Scheme
Prepared By:
Mrs. Swathi Darla
Assistant Professor,
Department of Information Science and Engineering
RVITM, Bengaluru – 560076
Email: [email protected]
MODULE IV
Integration and component-based software testing
4.1 Overview
Divides testing into four main levels of granularity: module, integration, system, and acceptance
test. Module or unit test checks module behavior against specifications or expectations;
integration test checks module compatibility; system and acceptance tests check behavior of the
whole system with respect to specifications and user needs, respectively
While integration testing may to some extent act as a process check on module testing (i.e., faults
revealed during integration test can be taken as a signal of unsatisfactory unit testing), thorough
integration testing cannot fully compensate for sloppiness at the module level. In fact, the quality
of a system is limited by the quality of the modules and components from which it is built, and
even apparently noncritical modules can have widespread effects.
Side-effects on parameters or resources Example: A module often uses resources that are not
explicitly mentioned in its interface. Integration problems arise when these implicit effects of one
module interfere with those of another. For example, using a temporary file "tmp" may be
invisible until integration with another module that also attempts to use a temporary file "tmp" in
the same directory of scratch files Missing or misunderstood functionality
Dynamic mismatches many languages and frameworks allow for dynamic binding. Problems may
be caused by failures in matching’s when modules are integrated Example: Polymorphic calls
may be dynamically bound to incompatible methods
Integration testing proceeds incrementally with assembly of modules into successively larger
subsystems. Incremental testing is preferred, first, to provide the earliest possible feedback on
integration problems. In addition, controlling and observing the behavior of an integrated
collection of modules grows in complexity with the number of modules and the complexity of
their interactions
Big bang testing One extreme approach is to avoid the cost of scaffolding by waiting until all
modules are integrated, and testing them together - essentially merging integration testing into
system testing. In this big bang approach, neither stubs nor drivers need be constructed, nor must
the development be carefully planned to expose well-specified interfaces to each subsystem.
These savings are more than offset by losses in observability, diagnosability, and feedback
Structural integration test strategy: Among strategies for incrementally testing partially
assembled systems, we can distinguish two main classes: structural and feature oriented. In a
structural approach, modules are constructed, assembled, and tested together in an order based on
hierarchical structure in the design. Structural approaches include bottom-up, top-down, and a
combination sometimes referred to as sandwich or backbone strategy. Feature oriented strategies
derive the order of integration from characteristics of the application, and include threads and
critical modules strategies.
Top-down and bottom up testing: A top-down integration strategy begins at the top of the uses
hierarchy, including the interfaces exposed through a user interface or top-level application
program interface (API)
Sandwich or backbone: Integration may combine elements of the two approaches, starting from
both ends of the hierarchy and proceeding toward the middle. An early top-down approach may
result from developing prototypes for early user feedback, while existing modules may be
integrated bottom-up. This is known as the sandwich or backbone strategy
Critical module: Critical module integration testing focuses on modules that pose the greatest
risk to the project. Modules are sorted and incrementally integrated according to the associated
risk factor that characterizes the criticality of each module. Both external risks (such as safety)
and project risks (such as schedule) can be considered.
Many software products are constructed, partly or wholly, from assemblies of prebuilt software
components. A key characteristic of software components is that the organization that develops a
component is distinct from the (several) groups of developers who use it to construct system
when reusing a component that has been in use in other applications for some time, one obtains
the benefit not only of test and analysis by component developers, but also of actual operational
use.
These advantages are balanced against two considerable disadvantages. First, a component
designed for wide reuse will usually be much more complex than a module designed for a single
use; a rule of thumb is that the development effort (including analysis and test) for a widely
usable component is at least twice that for a module that provides equivalent functionality for a
single application.
The interface specification of a component should provide all the information required for
reusing the component, including so-called nonfunctional properties such as performance or
capacity limits, in addition to functional behavior
The main problem facing test designers in the organization that produces a component is lack of
information about the ways in which the component will be used. A component may be reused in
many different contexts, including applications for which its functionality is an imperfect fit
Test designers cannot anticipate all possible uses of a component under test, but they can design
test suites for classes of use in the form of scenarios. Test scenarios are closely related to
scenarios or use cases in requirements analysis and design
Component contract or interface The component contract describes the access points and
parameters of the component, and specifies functional and nonfunctional behavior and any
conditions required for using the component.
Frameworks and design patterns Patterns are logical design fragments, while frameworks are
concrete elements of the application. Frameworks often implement patterns.
COTS The term commercial off-the-shelf, or COTS, indicates components developed for the
sale to other organizations.
System, acceptance, and regression testing are all concerned with the behavior of a software
systemas a whole, but they differ in purpose.
System testing can be considered the culmination of integration testing, and passing all system
tests is tantamount to being complete and free of known bugs. The system test suite may share
some test cases with test suites used in integration and even unit testing, particularly when a
thread-based or spiral model of development has been taken and subsystem correctness has been
tested primarily through externally visible features and behavior.
The appropriate notions of thoroughness in system testing are with respect to the system
specification and potential usage scenarios, rather than code or design. Each feature or specified
behavior of the system should be accounted for in one or several test cases
Some system properties, including performance properties like latency between an event and
system response and reliability properties like mean time between failures, are inherently global.
Global properties like performance, security, and safety are difficult to specify precisely and
operationally, and they depend not only on many parts of the system under test, but also on its
The purpose of acceptance testing is to guide a decision as to whether the product in its current
state should be released. The decision can be based on measures of the product or process.
Quantitative goals for dependability, including reliability, availability, and mean time between
failure
Systematic testing, which includes all of the testing techniques presented heretofore in this book,
does not draw statistically representative samples. Their purpose is not to fail at a "typical" rate,
but to exhibit as many failures as possible. They are thus unsuitable for statistical testing.
A less formal, but frequently used approach to acceptance testing is testing with users. An early
version of the product is delivered to a sample of users who provide feedback on failures and
usability. Such tests are often called alpha and beta tests. The two terms distinguish between
testing phases. Often the early or alpha phases are performed within the developing organization,
while the later or beta phases are performed at users' sites.
In alpha and beta testing, the user sample determines the operational profile
Usability
A usable product is quickly learned, allows users to work efficiently, and is pleasant to use.
Usability involves objective criteria such as the time and number of operations required to
perform tasks and the frequency of user error, in addition to the overall, subjective satisfaction of
users
Even if usability is largely based on user perception and thus is validated based on user feedback,
it can be verified early in the design and through the whole software life cycle. The process of
verifying and validating usability includes the following main steps:
Testing early prototypes with end users to explore their mental model (exploratory test),
evaluate alternatives (comparison test), and validate software usability. A prototype for early
assessment of usability may not include any functioning software; a cardboard prototype may be
as simple as a sequence of static images presented to users by the usability tester.
Testing incremental releases with both usability experts and end users to monitor progress and
System and acceptance testing that includes expert-based inspection and testing, userbased
testing, comparison testing against competitors, and analysis and checks often done
automatically, such as a check of link connectivity and verification of browser compatibility.
User-based testing (i.e., testing with representatives of the actual end-user population) is
particularly important for validating software usability. It can be applied at different stages, from
early prototyping through incremental releases of the final system, and can be used with different
goals: exploring the mental model of the user, evaluating design alternatives, and validating
against established usability requirements and standards.
Exploratory testing: The purpose of exploratory testing is to investigate the mental model of
end users. It consists of asking users about their approach to interactions with the system. For
example, during an exploratory test for the Chipmunk Web presence, we may provide users with
a generic interface for choosing the model they would like to buy, in order to understand how
users will interact with the system
comparison testing: The purpose of comparison testing is evaluating options. It consists of
observing user reactions to alternative interaction patterns. During comparison test we can, for
example, provide users with different facilities to assemble the desired Chipmunk laptop
configuration, and to identify patterns that facilitate users' interactions.
validation testing: The purpose of validation testing is assessing overall usability. It includes
identifying difficulties and obstacles that users encounter while interacting with the system, as well
as measuring characteristics such as error rate and time to perform a task.
Regression Testing
Testing activities that focus on regression problems are called (non) regression testing. Usually
"non" is omitted and we commonly say regression testing.
A simple approach to regression testing consists of reexecuting all test cases designed for
previous versions. Even this simple retest all approach may present nontrivial problems and
costs. Former test cases may not be re executable on the new version without modification, and
Test case maintenance: Changes in the new software version may impact the format of inputs
and outputs, and test cases may not be executable without corresponding changes. Even simple
modifications of the data structures, such as the addition of a field or small change of data types,
may invalidate former test cases, or outputs comparable with the new ones.
Scaffolding that interprets test case specifications, rather than fully concrete test data, can reduce
the impact of input and output format changes on regression testing
High-quality test suites can be maintained across versions by identifying and removing obsolete
test cases, and by revealing and suitably marking redundant test cases. Redundant cases differ
from obsolete, being executable but not important with respect to the considered testing criteria
Test case prioritization orders frequency of test case execution, executing all of them eventually
but reducing the frequency of those deemed least likely to reveal faults by some criterion
Prioritization can be based on the specification and code-based regression test selection
techniques described later in this chapter. In addition, test histories and fault-proneness models
can be incorporated in prioritization schemes. For example, a test case that has previously
revealed a fault in a module that has recently undergone change would receive a very high
priority, while a test case that has never failed (yet) would receive a lower priority, particularly if
it primarily concerns a feature that was not the focus of recent changes.
Regression test selection techniques are based on either code or specifications. Code based
selection techniques select a test case for execution if it exercises a portion of the code that has
been modified. Specification-based criteria select a test case for execution if it is relevant to a
portion of the specification that has been changed. Code based regression test techniques can be
supported by relatively simple tools. They work even when specifications are not
Properly maintained.
Regression testing criteria may select a large portion of a test suite. When a regression
test suite is too large, we must further reduce the set of test cases to be executed.
Random sampling is a simple way to reduce the size of the regression test suite. high-
priority test cases are selected more often than low-priority test cases. With a good
selection strategy, all test cases are executed sooner or later
Execution history priority schema Priorities can be assigned in many ways. A simple
priority scheme assigns priority according to the execution history: Recently executed
test cases are given low priority, while test cases that have not been recently executed
are given high priority. In the extreme, heavily weighting execution history
approximates round robin selection.
Fault revealing priority schema Other history-based priority schemes predict fault
detection effectiveness. Test cases that have revealed faults in recent versions are
given high priority. Faults are not evenly distribute
The traditional model of software development is the Waterfall model, which is drawn as a V
in. In this view, information produced in one of the development phases constitutes the basis
for test case identification at that level. Nothing controversial here: we certainly would hope
that system test cases are somehow correlated with the requirements specification, and that
unit test cases are derived from the detailed design of the unit. Two observations: there is a
clear presumption of functional testing here, and there is an implied “bottom-up” testing
order.
4.4.1 Alternative Life Cycle Models
Since the early 1980s, practitioners have devised alternatives in response to shortcomings of
the traditional waterfall model of software development Common to all of these alternatives
is the shift away from the functional decomposition to an emphasis on composition.
Decomposition is a perfect fit both to the top-down progression of the waterfall model and to
the bottom-up testing order. One of the major weaknesses of waterfall development cited by
[Agresti 86] is the over-reliance on this whole paradigm. Functional decomposition can only
be well done when the system is completely understood, and it promotes analysis to the near
exclusion of synthesis.
The result is a very long separation between requirements specification and a completed
system, and during this interval, there is no opportunity for feedback from the customer.
Composition, on the other hand, is closer the way people work: start with something known
and understood, then add to it gradually, and maybe remove undesired portions. There is a
very nice analogy with positive and negative sculpture. In negative sculpture, work proceeds
by removing unwanted material, as in the mathematician’s view of sculpting Michelangelo’s
David: start with a piece of marble, and simply chip away all non-David. Positive sculpture is
often done with a medium like wax. The central shape is approximated, and then wax is
either added or removed until the desired shape is attained.
We could show this with pronounced feedback loops among waterfall phases, but the
As the object-oriented paradigm proceeds, details “bubble up” through specification, design,
and coding phases, but at each stage, some of the “flow” drops back to the previous phase(s).
This model captures the reality of the way people actually work (even with the traditional
approaches).
4.6 Formulations of the SATM System
In this and the next three chapters, we will relate our discussion to a higher level example, the
Simple Automatic Teller Machine (SATM) system. there are function buttons B1, B2, and
B3, a digit keypad with a cancel key, slots for printer receipts and ATM cards, and doors for
deposits and cash withdrawals. The SATM system is described here in two ways: with a
structured analysis approach, and with an object-oriented approach. These descriptions are
not complete, but they contain detail sufficient to illustrate the testing techniques under
discussion.
The functional and data models were drawn with the Deft CASE tool from Sybase Inc. That
tool identifies external devices (such as the terminal doors) with lower case letters, and
elements of the functional decomposition with numbers (such as 1.5 for theValidate Card
function). The open and filled arrowheads on flow arrows signify whether the flow item is
simple or compound. The portions of the SATM system shown here pertain generally to the
personal identification number (PIN) verification portion of the system.
State = AwaitCard
AmaitPIN:
ValidatePIN(PiNok, PAN)
IF PINok TEEN ScreenDriver(2, null)
State = AwaitTransELSE
ScreenDriver(4, null)
St at e = Amain Card
AmaitTrans:ManageTransaction
State = CloseSession
CloseSession:IF NewTransactionReguest
TEEN State = AmaitTrans
ELSE PrintReceipt
PoseTransaceionLocal
CloseSession
ControlCardRoller(eject)
State = AmaitCard
End, (CASE State)
END. (Main program SAD)
The ValidatePIN procedure is based on another finite state machine, in which states refer
to the number of PIN entry attempts.
Procedure ValidatePIN(PINok, PAN) GetPINforPAN(PAN, ExpectedPlN)
Try = First
CASE Try OF
First:ScreenDriver(2, null)
GetPIN(EnteredPIN)
IF EnteredPIN = ExpectedPlN THEN PiNok = TRUE
RETURN
ELSE ScreenDriver(3, null)
Try = Second
Second:ScreenDriver(2, null)
GetPIN(EneeredPIN)
IF EnteredPIN = ExpectedPlN THEN PiNok = TRUE
RETURN
A thread is a construct that refers to execution time behavior; when we test a system,
we use test cases to select (and execute) threads. We can speak of levels of threads:
system threads describe system level behavior, integration threads correspond to
integration level behavior, and unit threads correspond to unit level behavior. Many
authors use the term, but few define it, and of those that do, the offered definitions
aren’t very helpful. For now, we take “thread” to be a primitive term, much like
function anddata.
In the next two chapters, we shall see that threads are most often recognized in terms of
the way systems are described and developed. For example, we might think of a thread
as a path through a finite state machine description of a system, or we might think of a
thread as something that is determined by a data context and a sequence of port level
input events, such as those in the context diagram of the SATM system. We could also
think of a thread as a sequence of source statements, or as a sequence of machine
instructions. The point is, threads are a generic concept, and they exist independently of
how a system is described and developed.
3. Insertion of a valid card, a correct PIN entry attempt, followed by a balance inquiry.
6. Insertion
of a valid card, a correct PIN entry attempt, followed by an attempt to withdraw
more cash than the account balance.
This decomposition is the basis for the usual view of integration testing. It is important to
remember that such a decomposition is primarily a packaging partition of the system. As
We can dispense with the big bang approach most easily: in this view of integration, all the units are
compiled together and tested at once. The drawback to this is that when (not if!) a failure is observed,
there are few clues to help isolate the location(s) of the fault.
Once all the stubs for SATM main have been provided, we test the main program as if it were a stand-
alone unit. We could apply any of the appropriate functional and structural techniques, and look for
faults. When we are convinced that the main program logic is correct, we gradually replace stubs with
the actual code. Even this can be problematic. Would we replace all the stubs at once? If we did, we
Predecessors Successors
1 1 9, 10, 12
6
1 1 11, 14, 18
7
1 17 14, 15
8
1 1 14, 15
9
23 22 14, 15
24 22 14,15
25 22 15
We can always compute the number of neighborhoods for a given call graph. There will be one
neighborhood for each interior node, plus one extra in case there are leaf nodes connected directly to
the root node. (An interior node has a non-zero indegree and a non-zero outdegree.)
4.9 Path Based Integrations
Much of the progress in the development of mathematics comes from an elegant pattern: have a clear
idea of where you want to go, and then define the concepts that take you there. We do this here for path
based integration testing, but first we need to motivate the definitions.
When a unit executes, some path of source statements is traversed. Suppose that there is a call to another
unit along such a path: at that point, control is passed from the calling unit to the called unit, where some
other path of source statements is traversed. We cleverly ignored this situation in Part III, because this is
a better place to address the question. There are two possibilities: abandon the single- entry, single exit
precept and treat such calls as an exit followed by an entry, or “suppress” the call statement because
control eventually returns to the calling unit anyway. The suppression choice works well for unit testing,
Sem-VI, Software Testing(21IS63)
Page 27 of 27
RV Institute of Technology and Management ®
but it is antithetical to integration testing. The first guideline for MM-Paths: points of quiescence are
“natural” endpoints for an MM-Path. Our second guideline also serves to distinguish integration from
system testing.
Our second guideline: atomic system functions are an upper limit for MM-Paths: we don’t want MM-
Paths to cross ASF boundaries. This means that ASFs represent the seam between integration and system
testing. They are the largest item to be tested by integration testing, and the smallest item for system
testing. We can test an ASF at both levels. Again, the digit entry ASF is a good example. During system
testing, the port input event is a physical key press that is detected by KeySensor and sent to GetPIN as a
string variable. (Notice that KeySensor performs the physical to logical transition.) GetPIN determines
whether a digit key or the cancel key was pressed, and responds accordingly. (Notice that button presses
are ignored.) The ASF terminates with either screen 2 or 4 being displayed. Rather than require system
keystrokes and visible screen displays, we could use a driver to provide these, and test the digit entry
ASF via integration testing. We can see this using our continuing example.