Software Testing
Software Testing
Introduction:
Purpose of Testing:
Testing consumes atleast half of the time and work required to produce a functional program.
• MYTH: Good programmers write code without bugs. (Its wrong!!!)
• History says that even well written programs still have 1-3 bugs per hundred statements.
• The main purpose of testing is to catch bugs.
• Productivity and Quality in software:
◦ In production of comsumer goods and other products, every
manufacturing stage is subjected to quality control and testing from component to final
stage.
◦ If flaws are discovered at any stage, the product is either discarded or cycled back for
rework and correction.
◦ Productivity is measured by the sum of the costs of the material, the rework, and the
discarded components, and the cost of quality assurance and testing.
Testing and Test Design are parts of quality assurance should also focus on bug prevention. A
prevented bug is better than a detected and corrected bug.
Phases in a tester's mental life can be categorised into the following 5 phases:
1. Phase 0: (Until 1956: Debugging Oriented) There is no difference between testing and
debugging. Phase 0 thinking was the norm in early
days of software development till testing emerged as a discipline.
2. Phase 1: (1957-1978: Demonstration Oriented) The purpose of testing here is to show that
software works. Highlighted during the late 1970s. This failed because the probability of
showing that software works 'decreases' as testing increases. i.e. The more you test, the more
likely you’ll find a bug.
3. Phase 2: (1979-1982: Destruction Oriented) The purpose of testing is to show that software
doesnt work. This also failed because the software will never get released as you will find
one bug or the other. Also, a bug corrected may also lead to another bug.
4. Phase 3: (1983-1987: Evaluation Oriented) The purpose of testing is not to prove anything
but to reduce the perceived risk of not working to an acceptable value (Statistical Quality
Control). Notion is that testing does improve the product to the extent that testing catches
bugs and to the extent that those bugs are fixed. The product is released when the confidence
on that product is high enough. (Note:This is applied to large software products with
millions of code and years of use.)
5. Phase 4: (1988-2000: Prevention Oriented) Testability is the factor considered here. One
reason is to reduce the labour of testing. Other reason is to check the testable and non-
1
testable code. Testable code has fewer bugs than the code that's hard to test. Identifying the
testing techniques to test the code is the main key here.
• Testing Versus Debugging: Many people consider both as same. Purpose of testing is to show
that a program has bugs. The purpose of testing is to find the error or misconception that led to
the program's failure and to design and implement the program changes that correct the error.
• Debugging usually follows testing, but they differ as to goals, methods and most important
psychology. The below tab le shows few important differences between testing and debugging.
Testing Debugging
Testing starts with known conditions, uses Debugging starts from possibly unknown intial
predefined procedures and has predictable conditions and the end can not be predicted except
outcomes. statistically.
Testing can and should be planned, designed Procedure and duration of debugging cannot be so
and scheduled. constrained.
Testing is a demonstration of error or
Debugging is a deductive process.
apparent correctness.
Debugging is the programmer's vindication
Testing proves a programmer's failure.
(Justification).
Testing, as executes, should strive to be
Debugging demands intutive leaps,
predictable, dull, constrained, rigid and
experimentation and freedom.
inhuman.
Much testing can be done without design Debugging is impossible without detailed design
knowledge. knowledge.
Testing can often be done by an outsider. Debugging must be done by an insider.
Much of test execution and design can be
automated.
• Function Versus Structure: Tests can be designed from a functional or a structural point of
view. In functional testing, the program or system is treated as a blackbox. It is subjected to
inputs, and its outputs are verified for conformance to specified behaviour. Functional
testing takes the user point of view- bother about functionality and features and not the
program's implementation. Structural testing does look at the implementation details. Things
such as programming style, control method, source language, database design, and coding
details dominate structural testing.
• Both Structural and functional tests are useful, both have limitations, and both target
different kinds of bugs. Functional tets can detect all bugs but would take infinite time to do
so. Structural tests are inherently finite but cannot detect all errors even if completely
executed.
• Designer Versus Tester: Test designer is the person who designs the tests where as the tester
is the one actually tests the code. During functional testing, the designer and tester are
probably different persons. During unit testing, the tester and the programmer merge into
one person.
2
• Tests designed and executed by the software designers are by nature biased towards
structural consideration and therefore suffer the limitations of structural testing.
• Builder Versus Buyer: Most software is written and used by the same organization.
Unfortunately, this situation is dishonest because it clouds accountability. If there is no
separation between builder and buyer, there can be no accountability.
2. Buyer: Who pays for the system in the hope of profits from providing services.
3. User: Ultimate beneficiary or victim of the system. The user's interests are also guarded by.
5. Operator: Who has to live with the builders' mistakes, the buyers' murky (unclear)
specifications, testers' oversights and the users' complaints.
Above figure is a model of testing process. It includes three models: A model of the environment, a
model of the program and a model of the expected bugs.
• ENVIRONMENT:
3
◦ A Program's environment is the hardware and software required to
make it run. For online systems, the environment may include communication lines, other
systems, terminals and operators.
◦ The environment also includes all programs that interact with and are used to create the
program under test - such as OS, linkage editor, loader, compiler, utility routines.
◦ Because the hardware and firmware are stable, it is not smart to blame the environment for
bugs.
• PROGRAM:
◦ If simple model of the program doesnot explain the unexpected behaviour, we may have to
modify that model to include more facts and details. And if that fails, we may have to
modify the program.
• BUGS:
◦ Bugs are more insidious (deceiving but harmful) than ever we expect
them to be.
◦ An unexpected test result may lead us to change our notion of what a bug is and our model
of bugs.
◦ Some optimistic notions that many programmers or testers have about bugs are usually
unable to test effectively and unable to justify the dirty tests most programs need.
1. Frequency: How often does that kind of bug occur? Pay more attention to the more frequent
bug types.
2. Correction Cost: What does it cost to correct the bug after it is found? The cost is the sum of
2 factors: (1) the cost of discovery (2) the cost of correction. These costs go up dramatically
later in the development cycle when the bug is discovered. Correction cost also depends on
system size.
3. Installation Cost: Installation cost depends on the number of installations: small for a single
user program but more for distributed systems. Fixing one bug and distributing the fix could
exceed the entire system's development cost.
4. Consequences: What are the consequences of the bug? Bug consequences can range from
mild to catastrophic.
1. Mild: The symptoms of the bug offend us aesthetically (gently); a misspelled output or a
misaligned printout.
2. Moderate: Outputs are misleading or redundant. The bug impacts the system's performance.
3. Annoying: The system's behaviour because of the bug is dehumanizing. E.g. Names are
truncated orarbitarily modified.
4. Disturbing: It refuses to handle legitimate (authorized / legal) transactions. The ATM wont
give you money. My credit card is declared invalid.
5. Serious: It loses track of its transactions. Not just the transaction itself but the fact that the
transaction occurred. Accountability is lost.
6. Very Serious: The bug causes the system to do the wrong transactions. Instead of losing your
paycheck, the system credits it to another account or converts deposits to withdrawals.
7. Extreme: The problems aren't limited to a few users or to few transaction types. They are
frequent and arbitrary instead of sporadic infrequent) or for unusual cases.
5
8. Intolerable: Long term unrecoverable corruption of the database occurs and the corruption is
not easily discovered. Serious consideration is given to shutting the system down.
9. Catastrophic: The decision to shut down is taken out of our hands because the system fails.
10. Infectious: What can be worse than a failed system? One that corrupt other systems even
though it doesnot fall in itself ; that erodes the social physical environment; that melts
nuclear reactors and starts war.
TAXONOMY OF BUGS:
• There is no universally correct way categorize bugs. The taxonomy is not rigid.
• A given bug can be put into one or another category depending on its history and the
programmer's state of mind.
Requirements and specifications developed from them can be incomplete ambiguous, or self-
contradictory. They can be misunderstood or impossible to understand.
The specifications that don't have flaws in them may change while the design is in progress. The
features are added, modified and deleted.
Requirements, especially, as expressed in specifications are a major source of expensive bugs.
The range is from a few percentage to more than 50%, depending on the application and
environment. What hurts most about the bugs is that they are the earliest to invade the system and
the last to leave.
2.Feature Bugs:
6
case is easier to detect and correct. A wrong feature could have deep design implications.
-Removing the features might complicate the software, consume more resources, and foster more
bugs.
3.Feature Interaction Bugs:
Providing correct, clear, implementable and testable feature specifications is not enough.
Features usually come in groups or related features. The features of each group and the interaction
of features with in the group are usually well tested.
The problem is unpredictable interactions between feature groups or even between individual
features. For example, your telephone is provided with call holding and call forwarding. The
interactions between these two features may have bugs.
Every application has its peculiar set of features and a much bigger set of unspecified feature
interaction potentials and therefore result in feature interaction bugs.
Most feature bugs are rooted in human to human communication problems. One solution is to use
high-level, formal specification languages or systems.
Such languages and systems provide short term support but in the long run, does not solve the
problem.
The specification problem has been shifted to a higher level but not eliminated.
• Control and sequence bugs include paths left out, unreachable code, improper nesting of loops,
loop- back or loop termination criteria incorrect, missing process steps, duplicated processing,
unnecessary processing, GOTO's, ill- conceived (not properly planned) switches, sphagetti code,
and worst of all, pachinko code.
• One reason for control flow bugs is that this area is amenable (supportive) to theoritical treatment.
Most of the control flow bugs are easily tested and caught in unit testing.
• Another reason for control flow bugs is that use of old code especially ALP & COBOL code are
dominated by control flow bugs.
Control and sequence bugs at all levels are caught by testing, especially structural testing, more
specifically path testing combined with a bottom line functional test based on a specification.
2. Logic Bugs:
7
• Bugs in logic, especially those related to misundertanding how case statements and
logic operators behave singly and combinations
• If the bugs are parts of logical (i.e. boolean) processing not related to control flow,
they are characterized as processing bugs.
• If the bugs are parts of a logical expression (i.e control-flow statement) which is used
to direct the control flow, then they are categorized as control- flow bugs.
3. Processing Bugs:
4, Initialization Bugs:
Initialization bugs are common. Initialization bugs can be improper and superfluous.
Superfluous bugs are generally less harmful but can affect performance. Typical initialization bugs
include: Forgetting to initialize the variables before first use, assuming that they are initialized
elsewhere, initializing to the wrong format, representation or type etc Explicit declaration of all
variables, as in Pascal, can reduce some initialization problems.
3.DATA BUGS:
• Data bugs include all bugs that arise from the specification of
data objects, their formats, the number of such objects, and their initial values.
Data Bugs are atleast as common as bugs in code, but they are foten treated as if they didnot
exist at all.
Code migrates data: Software is evolving towards programs in which more and more of the
control and processing functions are stored in tables.
• Because of this, there is an increasing awareness that bugs in code are only half the battle
and the data problems should be given equal attention.
8
4 CODING BUGS:
Coding errors of all kinds can create any of the other kind of bugs.
• Syntax errors are generally not important in the scheme of things if the source
language translator has adequate syntax checking.
• If a program has many syntax errors, then we should expect many logic and coding
bugs.
• The documentation bugs are also considered as coding bugs which may mislead the
maintenance programmers.
1. External Interfaces: The external interfaces are the means used to communicate with
the world.
• The primary design criterion for an interface with outside world should be robustness.
• The external environment is fixed and the system must adapt to it but the
internal environment, which consists of interfaces with other components,
can be negotiated.
3. Hardware Architecture:
• The remedy for hardware architecture and interface problems is two fold: (1) Good
Programming and Testing (2) Centralization of hardware interface software in
programs written by hardware interface specialists.
9
4. Operating System Bugs:
5. Software Architecture:
• Routines can pass unit and integration testing without revealing such bugs.
• Many of them depend on load, and their symptoms emerge only when the
system is stressed.
• Sample for such bugs: Assumption that there will be no interrupts, Failure to
block or un block interrupts, Assumption that memory and registers were
initialized or not initialized etc
• Careful integration of modules and subjecting the final system to a stress test
are effective methods for these bugs.
• External mass storage units such as discs, are subdivided into memory
resource pools.
10
• Some resource management and usage bugs: Required resource not
obtained, Wrong resource used, Resource is already in use, Resource dead
lock etc
8. Integration Bugs:
• Integration bugs are bugs having to do with the integration of, and with the
interfaces between, working and tested components.
The integration bugs do not constitute a big bug category(9%) they are expensive
category because they are usually caught late in the game and because they force changes
in several components and/or data structures.
9. System Bugs:
System bugs covering all kinds of bugs
that cannot be ascribed to a component or to their simple interactions, but result from the
totality of interactions between many components such as programs, data, hardware, and
the operating systems.
• There can be no meaningful system testing until there has been thorough
component and integration testing.
• System bugs are infrequent(1.7%) but very important because they are often found
only after the system has been fielded.
• Testing: testers have no immunity to bugs. Tests require complicated scenarios and
databases.
• They require code or the equivalent to execute and consequently they can have bugs.
11
• Test criteria: if the specification is correct, it is correctly interpreted and
implemented, and a proper test has been designed; but the criterion by which the
software's behavior is judged may be incorrect or impossible. So, a proper test
criteria has to be designed. The more complicated the criteria, the likelier they are to
have bugs.
1. Test Debugging: The first remedy for test bugs is testing and debugging the
tests. Test debugging, when compared to program debugging, is easier
because tests, when properly designed are simpler than programs and donot
have to make concessions to efficiency.
2. Test Quality Assurance: Programmers have the right to ask how quality in
independent testing is monitored.
PATH TESTING:
◦ Path Testing is the name given to a family of test techniques based on judiciously selecting a
set of test paths through the program.
◦ If the set of paths are properly chosen then we have achieved some measure of test
thoroughness. For example, pick enough paths to assure that every source statement has
been executed at least once.
◦ Path testing techniques are the oldest of all structural test techniques.
◦ Path testing is most applicable to new software for unit testing. It is a structural technique.
12
Assumptions:
Observations:
The control flow graph is a graphical representation of a program's control structure. It uses the
elements named process blocks, decisions, and junctions.
Flow Graph Elements:A flow graph contains four different types of elements.
(1) Process Block (2) Decisions (3) Junctions (4) Case Statements
1. ProcessBlock:
• It is a sequence of statements such that if any one of statement of the block is executed, then
all statement thereof are executed.
• Formally, a process block is a piece of straight line code of one statement or hundreds of
statements.
• A process has one entry and one exit. It can consists of a single statement or instruction, a
sequence of statements or instructions, a single entry/exit subroutine, a macro or function
call, or a sequence of these.
2. Decisions:
3. Case statements
• A junction is a point in the program where the control flow can merge.
13
• Examples of junctions are: the target of a jump or skip instruction in ALP, a label that is a target
of GOTO.
◦ The flowchart focuses on process steps, where as the flow graph focuses on control
flow of the program.
◦ The act of drawing a control flow graph is a useful tool that can help us clarify the
control flow and data flow issues.
14
PATH TESTING - PATHS, NODES AND LINKS:
◦ A path may go through several junctions, processes, or decisions, one or more times.
◦ The segment is a link - a single process that lies between two nodes.
◦ The length of path measured by the number of links in it and not by the number of
the instructions or statements executed along that path.
◦ The name of a path is the name of the nodes along the path.
◦ There are many paths between the entry and exit of a typical routine.
◦ Every decision doubles the number of potential paths. And every loop multiplies the
number of potential paths by the
number of different iteration values possible for the loop.
3. Exercise every branch and case statement, in each direction at least once
◦ Any testing strategy based on paths must at least both exercise every instruction and
take branches in all directions.
◦ A set of tests that does this is not complete in an absolute sense, but it is complete in
the sense that anything less
must leave something untested.
• Execute all possible control flow paths through the program: typically, this is restricted to all
possible entry/exit paths through the program.
15
• If we achieve this prescription, we are said to have achieved 100% path coverage. This is the
strongest criterion in the path testing strategy family: it is generally impossible to achieve.
• Execute all statements in the program at least once under some test. If we do enough tests to
achieve this, we are said to have achieved 100% statement coverage.
• This is the weakest criterion in the family: testing less than this for new software is
unconscionable (unprincipled or can not be accepted) and should be criminalized.
• Execute enough tests to assure that every branch alternative has been exercised at least once
under some test.
• If we do enough tests to achieve this prescription, then we have achieved 100% branch
coverage.
• For structured software, branch testing and therefore branch coverage strictly includes
statement
coverage.
• PREDICATE: The logical function evaluated at a decision is called Predicate. The direction taken
at a decision depends on the value of decision variable. Some examples are: A>0, x+y>=90.......
• PATH PREDICATE: A predicate associated with a path is called a Path Predicate. For example, "x
is greater than zero", "x+y>=90", "w is either negative or equal to 10 is true" is a sequence of
predicates whose truth values will cause the routine to take a specific path.
• If you cant find a solution to any of the sets of inequalities, the path is un achievable.
PATH SENSITIZATION:
• The act of finding a set of solutions to the path predicate expression is called PATH
SENSITIZATION.
16
PATH PREDICATE EXPRESSIONS:
• A path predicate expression is a set of boolean expressions, all of which must be satisfied to
achieve the
selected path.
Example:
X1+3X2+17>=0
X3=17
X4-X1>=14X2
Any set of input values that satisfy all of the conditions of the path predicate expression will force
the routine to the path.
Some times a predicate can have an OR in it.
Example:
A: X5 > 0
B: X1 + 3X2 + 17 >= 0 C: X3 = 17
D: X4 - X1 >= 14X2
E: X6 < 0
B: X1 + 3X2 + 17 >= 0 C: X3 = 17
D: X4 - X1 >= 14X2
TESTING BLINDNESS:
Testing Blindness is a pathological (harmful) situation in which the desired path is achieved for the
wrong reason.
There are three types of Testing Blindness:
1. Assignment Blindness:
• Assignment blindness occurs when the buggy predicate appears to work correctly because
the specific value chosen for an assignment statement works with both the correct and
incorrect predicate.
• For Example:
• If the test case sets Y=1 the desired path is taken in either case, but there is still a bug.
Correct Buggy
X= 7 X= 7
........ ........
If the test case sets Y=1 the desired path is taken in either case, but there is still a bug.
2. EqualityBlindness:
• Equality blindness occurs when the path selected by a prior predicate results in a value that works
both for the correct and buggy predicate.
17
• For Example:
Correct Buggy
if Y = 2
if Y = 2 then ........
then ........
if X+Y > 3 then ...
if X > 1 then ...
• The first predicate if y=2 forces the rest of the path, so that for any positive value of x. the path
taken at the second predicate will be the same for the correct and buggy version.
3.Self Blindness:
Self blindness occurs when the buggy predicate is a multiple of the correct predicate
and as a result is indistinguishable along that path. For Example:
Correct Buggy
X= A X= A
........ ........
if X-1 > 0 if X+A-2 > 0
then ... then ...
The assignment (x=a) makes the predicates multiples of each other, so the direction taken is the
same for the correct and buggy version.
PATH INSTRUMENTATION:
• Path instrumentation is what we have to do to confirm that the outcome was achieved by the
intended path.
• Co-incidental Correctness: The coincidental correctness stands for achieving the desired
outcome for wrong reason.
•
Figure 2.11: Coincidental Correctness
The above figure is an example of a routine that, for the (unfortunately) chosen input value
(X = 16), yields the same outcome (Y = 2) no matter which case we select. Therefore, the
tests chosen this way will not tell us whether we have achieved coverage. For example, the
five cases could be totally jumbled and still the outcome would be the same. Path
Instrumentation is what we have to do to confirm that the outcome was achieved by the
intended path.
• If we run the tested routine under a trace, then we have all the information we
need to confirm the outcome and, furthermore, to confirm that it was
achieved by the intended path.
• The trouble with traces is that they give us far more information than we
need. In fact, the typical trace program provides so much information that
confirming the path from its massive output dump is more work than
simulating the computer by hand to confirm the path.
• Instrument the links so that the link's name is recorded when the link is
executed.
• The succession of letters produced in going from the routine's entry to its
exit should, if there are no bugs, exactly correspond to the path name.
Why Single Link Markers aren't enough: Unfortunately, a single link marker may not do the trick
because links can be chewed by open bugs.
19