Anda di halaman 1dari 26

UNIT – II

FLOWGRAPHS & PATH TESTING


1 BASICS OF PATH TESTING:

Path testing based on the use of program’s control flow as a structural model is a cornerstone of
testing. Path testing is the name given to a family of test technique based on selecting the set of test paths
through the program.

1.2 MOTIVATION:
 Path testing techniques are the oldest of all structural test techniques.
 It is a common sense idea of executing every statement and branch at least once under some test case.
 It is most applicable to new software for unit testing. It is a structural technique.
 It requires complete knowledge about structure. It is most often used by programmers to unit test their
own code.
 The effectiveness of path testing reduces rapidly as the size of the unit increases.
 Path testing is rarely used for system testing. For the programmer, it is best testing technique.

1.3 THE BUG ASSUMPTION:


The bug assumption for the path testing strategies is that something has gone wrong with the software that
makes it take a different path than intended.
Ex: - Path GOTO X is taken where GOTO Y had been intended.
The effectiveness of path testing for structured programming language prevents many of the bugs
targeted by path testing. Old code like Assembly language, COBOL, FORTRAN, and BASIC, has a higher
proportion of control flow bugs than contemporary code.

1.4 CONTROL FLOW GRAPHS:


The Control Flowgraph is a graphical representation of a programs control structure. It uses the elements:
process blocks, decisions, and junctions.

1.4.1 PROCESS BLOCK:


 Process block is a sequence of program statements uninterrupted by either decisions or junctions.
 A process block can be one source statement or hundreds.
 Once a process block is initiated, every statement within it will be executed. Hence, a process block is a
piece of straight-line code.
 A process has one entry and one exit. It can consist of a statement (s), a single-entry/single-exit
subroutine, a function call etc.
 From the point of view of path testing, the details of a process block are not important, as they do not
affect the control flow.
Do
 A process block is represented as follows -- Process A

1.4.2 DECISIONS AND CASE STATEMENTS:


 Decision is a program point at which the control flow can diverge. Most decisions are two-way/binary.
Some are 3-way branches.
Ex: Machine language conditional branch, skip instructions, IF, IF-ELSE etc.
 A case statement is a multi-way branch/decision statement.
Ex: A jump table in assembly language, the FORTRAN-computed GOTO and assigned GOTO, & the
PASCAL CASE statement.
YES: DO ...
 A Decision Statement is represented as --

IF
CASE 1
 A Case Statement is represented as -- 1

CASE 2
2

CASE N
N
1.4.3 JUNCTIONS
 A junction is a point in the program where the control flow can merge.
Ex: The target of jump or skip instruction in assembly language, a label that is the target of a GOTO, the
END-IF and CONTINUE statements in FORTRAN and the PASCAL statements labels, END and UNTIL.
 A Junction is represented as – here, 1 & 2 are junctions.
1 2

1.4.4 CONTROL FLOWGRAPHS VERSUS FLOWCHARTS

 A programs flowchart resembles a control flowgraph. In control flowgraph, the details of what is in a
process block is not of importance i.e., the entire block is shown as a single process. In flowchart, every
single step of execution is shown.
 A flowgraph concentrates on control flow whereas a flowchart concentrates on the sequence of steps
performed to solve a problem.
 If there are 100 statements in a program, then a flowchart contains 100 boxes representing each step.
This leads to visual complexity. In Flowgraph, the visual complexity is reduced.
 The flowchart forces many off-page connectors, which confuse the control flow whereas the flowgraph
reduces the number of connectors.
 The flowgraph is a compact representation and is easier to follow whereas the flowchart includes too
much information and hence is complex.
 A detailed flowchart may not be an effective step in the design process, but the act of drawing a control
flowgraph is a useful tool that can help us clarify the control flow and data flow issues.
 Flowcharts are rarely used today. A flowchart was a first step toward the control flow graph.

1.4.5 NOTATIONAL EVOLUTION:

The control flowgraph is a simplified representation of program’s structure.


Ex: Consider the following program –
Z=X+Y
V=X- Y
IF ( Z >=0)
GOTO SAM
Z=Z–1
Y=Y+Z
U=Z+1
JOE: Z = Z + V
SAM: IF ( V == 0)
GOTO JOE
V=V–1
U=Z*V

The flow chart for the above program is shown below:


YES
Z>=0 SAM
INPUT X, Y Z=X+Y V=X-Y Y

NO

Y=Y+Z Z=Z-1
YES
JOE SAM V=0? JOE
U=Z+1 Z=Z+V

NO

V=V-1

END
U=Z*V

In this first step, we have the typical one-for-one classical flow chart. The complexity has increased, clarity has
decreased, and that we had to add auxiliary labels, which have no actual no program part. In the second step,
we merged the process steps and replaced them with the single process box.

YES
Z>=0 SAM
PROCESS 1

NO

YES
JOE PROCESS SAM V=0? JOE
PROCESS 2
3

NO

PROCESS 4 END

FIG: Control Flowgraph


1) The process boxes weren’t really needed. There is an implied process on every line joining junctions &
decisions.
2) We don’t need to know the specifics of the decisions.
3) The specific target label names aren’t important. So we can replace them by simple numbers.
1 2

3 4 5 6
5
FIG: Simplified Flowgraph Notation

There are 2 kinds of components: Circles and arrows that join circles. A circle with more than one arrow
leaving it is a decision. A circle with more than one arrow entering is a junction. The circles are called as nodes
and the arrows as links. The entry and exit are also denoted by circles. In the above figure node 1 and node 6
are represent start and end respectively. The links can also be names. This representation can still be
transformed to simplify the notation further.

FIG: Even simpler flow graph notation.

The alternate is to use a linked-list representation which is shown below:


1 (BEGIN) : 2
2 ( Z>=0) : 3(FALSE)
4(TRUE)
3 (JOE) : 4
4 (SAM) : 5
5 (V=0?) : 3(TRUE)
6(FALSE)
6 (END) :

1.4.6 FLOWGRAPH - PROGRAM CORRESPONDENCE:

A flow graph is a pictorial representation of a program and or not the program itself. The parts of the program
cannot be uniquely associated with the Flowgraph parts. This is because the program contains many
structures like IF-ELSE, junctions, decisions etc. The translation from a flowgraph element to a statement and
vice versa is not always unique. The failure to distinct between this correspondence may lead to bugs.
Ex: FOTRAN statement “IF (A=0) .AND. (B-1) THEN …”, has the alternate representation shown below:

YES
YES YES
IF
A=0&B=1 IF IF
? A=0? B=1?
? ?
NO
NO
NO

YES YES
IF IF
B=1? A=0?
? ?
NO

NO
The FORTRAN DO has 3 parts: a decision, an end-point junction, and a process that iterates the DO variable.
The FORTRAN-IF-THEN-ELSE has a decision, a junction, and 3 processes. Therefore, neither of these
statements can be translated into a single flow graph element.
An improper translation from flow graph to code during coding can lead to bugs, and an improper
translation during test design can lead to missing test cases and consequently, to undiscovered bugs.

1.4.7 FLOWGRAPH & FLOWCHART GENERATION:

The control flow graph is a simplified version of the earlier flow chart. Although there are many commercial
flowchart generating packages, there are very few flowgraph generators. Flow charts can be:
- Hand-drawn by the programmer,
- Automatically produced by a flowcharting program based on a mechanical analysis of
the source code,
- Semi automatically produced by a flowcharting program based in part on structural
analysis of the source code and in part on directions given by the programmer.
The semi automatic flowchart is most common with assembly language source code. A
flowcharting package that provides control over how statements are mapped into process boxes can be used
to produce a flowchart that is close to the control flow graph.
The designer’s original flow chart and the automatically produced flow chart would be identical, but
often they are not. The programmers design control flow graph/flow chart is a statement of intentions and
not a program. Those intentions become corrupted through the action of malevolent forces like keyboards,
compilers and other programmers. A typographical error in a case statement can cause a different path to be
implemented or can make a path unachievable. But the automatically produced flow chart is effective to
check the correspondence between the specification control flow graph and the flow chart produced from
code. It is a part of inspection or review.

1.5 PATH TESTING:

1.5.1 PATHS, NODES, & LINKS:

 A path through a program is a sequence of instructions or statements that starts at an entry, junction, or
decision and ends at another. A path may go through several junctions, processes or decisions one or
more times.
 Paths consist of segments. The smallest segment is a single process that lies between two nodes.
 A path segment is a succession of consecutive links that belongs to some path.
 The length of a path is measured by the number of links in it and by the number of instructions or
statements executed along the path.
 Because links are named by the pair of nodes they join, the name of the path is the name of the nodes
along the path.
 A path has a loop in it if any node name is repeated.
 The Entry/Exit path or complete path is the path that starts at an entry and goes to an exit.
 The interest in Entry/Exit path in testing is pragmatic because:
a. It’s difficult to set up and execute paths that start at an arbitrary statement.
b. It’s hard to stop at an arbitrary statement without setting traps or using patches and
c. Entry/Exit paths are what we want to test because we use routines that way.

1.5.2 MULTI-ENTRY/MULTI-EXIT ROUTINES:


 All routines and programs have a single entry and single exit. But, there may be a need write Multi-
Entry/Multi-Exit routines.
 Multi-Entry facility is supported only in assembly-level or low-level languages whereas Multi-Exit facility is
supported in high-level language also.
Ex: Multi-Exit routine in C Ex: Multi-Entry routine
int sum ( int a ) ------------
{ -----------
---------- JNZ 2000
---------- JMP 2050
--------- --------
If ( a > 0 ) ---------
return +1;
else if ( a == 0 ) 2000: ----------
return 0; ---------- subroutine
else 2050: ---------
return -1; ---------
}
 It is proper to jump out of a routine when an illogical condition has been detected. In this case it is clear
that any further processing along that path could damage the system’s operation or data. Under such
circumstances, the normal return path must be bypassed. This would need us to write Multi-Exit routines.
 Multi-Entry routines are used to save some code or coding time. In the above example, the subroutine
(available at location 2000) is called. If the JNZ condition is true, the subroutine will be entered into, from
location 2000. If the condition becomes false, then the subroutine will be executed from location 2050.
 The Multi-Entry routines can be converted into single-Entry routine by using an entry parameter that
directs the control flow within the routine to the proper point. Similarly, if a routine has several exit
points, an exit parameter should be used.
 The trouble with multi-entry and multi-exit routines is that it can be very difficult to determine what the
inter-process control flow is. The use of multi-entry and exits routines increases the number of entries and
exits and therefore the number of interfaces. This leads to more number of test cases.

1.5.3 FUNDAMENTAL PATH SELECTION CRITERIA:

There are many paths between the entry and exit of a typical routine. Every decision doubles the number of
paths and every loop multiplies the number of paths. If a routine has one loop, each pass through that loop
constitutes a different path through the routine, even though the same code is traversed each time. The
complete testing includes the following:
- Exercise every path from entry to exit.
- Exercise every statement or instruction at least once
- Exercise every branch and case statement, in each direction at least once.
If prescription 1 is followed, then prescription 2 & 3 are followed automatically. Prescriptions 2 & 3 appear to
be equivalent but they are not.
EX 1: The following is the correct version of the routine:
IF(X .LT. 0) GOTO 200
X = X+2A YES
200: X = X+A
300: CONTINUE
NO 30
X<O? X = X+A 20 X = X+A
0
0
?
For X negative, the output is X+A, while for X > 0, the output is X+2A.
Ex 2: Following prescription 2 and executing every statement, but not every branch, would not reveal the bug
in the following incorrect version.
IF (X .LT. 0) GOTO 200
200: X = X+A
300: CONTINUE YES
X = X+A 300
X<O 200

? NO

A negative value produces the correct answer. Every statement can be executed, but if the test cases do not
force each branch to be taken, the bug can remain hidden.
EX 3: The following is the test based on executing each branch but does not force the execution of all
statements.
IF(X) 200, 150, 300
100: X = X+A
GOTO 100
150: X = X+A 300 X = X+A

200: X = X+A
300: CONTINUE
<0

X 150 X = X+A 200 X = X+A 300

? =0

>0

The hidden loop around label 100 is not revealed by tests based on prescription 3 alone, because no test
forces the execution of statement 100 and the following GOTO statement.
A static analysis cannot determine whether a piece of code is or not reachable. Only a dynamic analysis
can determine whether code is reachable or not.

1.5.4 PATH TESTING CRITERIA:


Any testing strategy based on paths must at least both exercise every instruction and take branches in all
directions. Therefore, there are 3 different testing criteria or strategies. They are:
a) Path Testing (P∞) – Execute all possible control flow paths through the program. If we achieve this, then
we can said that 100% path coverage has been achieved. This is the strongest criteria in the path testing
strategy family but it is generally impossible to achieve.
b) Statement Testing (P1) – 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. An alternate,
equivalent characterization is to say that we have 100% node coverage. It is denoted by C1. This is the
weakest criterion in the family.
c) Branch Testing (P2) – 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. An alternative characterization is to say that we have 100% link coverage. It is
denoted by C2.

1.5.5 COMMON SENSE & STRATEGIES:


Branch and statement coverage are accepted today as the minimum mandatory testing requirement. The
justification for insisting on statement and branch coverage isn’t based on theory but on common sense.
a) Not testing a piece of code leaves a residue of bugs in the program in proportion to the size of the
untested code and the probability of bugs.
b) The high probability paths are always thoroughly tested if only to demonstrate that the system works
properly.
c) Logic errors & fuzzy thinking are inversely proportional to the probability of the paths execution.
d) The subjective probability of executing a path as seen by the routines designer and its objectives
execution probability are far apart.
e) The subjective evaluation of the importance of a code segment as judged by its programmer is biased
by aesthetic sense, ego, and familiarity.
Control Flow is the heart of the programming. Typical software has a density of conditional branches, loops
and other control-flow statements.

1.5.6 WHICH PATHS TO BE SELECTED?:

Pick enough paths to achieve C1+C2. It’s better to take many simple paths than a few complicated paths.
There’s no harm in taking paths that will exercise the same code more than once.
Ex: - Consider the following figure is an example of path selection.

g
YES

a YES c
1 2 3 5
b NO
NO d
e

4
YES
f
NO

FIG – An Example of Path Selection


Node 1 and 5 are START and END nodes respectively. Start at the beginning and take the most obvious path to
the exit. The most obvious path in the figure is (1, 2, 3, 5), if we names it by nodes. If we name it by links it is
abc. The next obvious path is abg. The remaining paths would be adec, adeg, adf. The following are some
practical suggestions:
 Draw the control flow graph on a single sheet of paper.
 Make several copies as many as you’ll need for coverage.
 Use a yellow highlighting marker to trace paths.
 Continue tracing paths until all lines on the master sheet are covered, indicating that you appear to
have achieved C1+C2.
As you trace the paths, create a table that shows the paths, the coverage status of each process and each
decision. The above paths lead to the following table:

Decisions Process-Links
Paths
2 3 4 a b c d e f g
abc Y N √ √ √
abg Y Y √ √ √
adec N N Y √ √ √ √
adeg N Y Y √ √ √ √
adf N N √ √ √

After tracing a covering path set on the master sheet and filled in the table for every path, check the following:
1) Does every decision have a YES and a NO in its column?
2) Has every case of all case statements been marked?
3) Is every 3-way branch covered?
4) Is every link covered at least once?

The paths can be selected to achieve path coverage without knowing anything about what the routine is
supposed to do. The path selection rules can be as follows:

1. Pick the simplest, functionally sensible entry/exit paths.


2. Pick additional paths as small variations from previous paths. Pick paths that do not have loops rather
than paths that do.
3. Pick additional paths that have no obvious functional meaning only if it’s necessary to provide
coverage.
4. Be comfortable with your chosen paths.
5. Don’t follow rules slavishly except for coverage.

It’s better to have several paths, each differing by only one thing, than one path that covers more but along
which several things change. Using small changes from one test to the next test may seem like more work,
however,

1. Small changes from path to path mean small, easily documented, and gradual changes in the test set
up.
2. Testing is experimenting. Good experiments rely on changing only one thing at a time. More changes
from test to test, leads to confusion.
3. As the hardware has become so cheap, the costs of testing extra paths are a few more microseconds of
computer time and the cost of additional documentation.
1.6 LOOPS:
There are only 3 kinds of loops:
 Nested loop
 Concatenated loop and
 Horrible loop
g

f NESTED LOOP

a b c d e
1 2 3 4 5 6

f g

1 a 2b 3
c
4
d
5
e
6
CONCATENATED LOOP
i

h 6 7

1 3 4 5 2
a b c d

e f HORRIBLE LOOPS
8
g

1.6.1 CASES FOR A SINGLE LOOP:


A single loop can be covered with 2 cases: looping and not looping. But experience shows that a many loop-
related bugs are not discovered by C1+C2.

CASE 1- Single loop, Zero minimum, N maximum, No excluded values


1. Try bypassing the loop. If you can’t, you either have a bug or zero is not the minimum and you have the
wrong case.
2. Could the loop-control variable be negative? What happens to such value?
3. One pass through the loop.
4. Two passes through the loop.
5. A typical number of iterations, unless covered by a previous test.
6. One less than the maximum number of iterations.
7. The maximum number of iterations.
8. One more than the maximum number of iterations.

The reason for 2 passes through the loop is based on a theorem by Huang’s twice-through theorem that
states that some data –flow anomalies, such as initialization problems, can be detected only by 2 passes
through the loop.

CASE 2 - Single loop, Non-zero minimum, N maximum, No excluded values


1. Try one less than the expected minimum.
2. The minimum number of iterations.
3. One more than the maximum number of iterations.
4. Once, unless covered by previous test.
5. Twice, unless covered by previous test.
6. A typical value.
7. One less than the maximum value.
8. The maximum number of iterations.
9. Attempt one more than the maximum number of iterations.

CASE 3 – Single loop with Excluded values


Treat single loop with excluded values as 2 sets of tests consisting of loops without excluded values.
EX: The total range of the loop-control variable was 1-20., but the values 7,8,9,& 10 were excluded. The 2 sets
of tests are 1-6 and 11-20. The test cases to attempt would be 0,1,2,4,6,7 for the first range and
10,11,15,19,20,21 for the second range. The underlined cases are not supposed to work, but they should be
attempted. Also, try a value within the excluded range, such as 8.

1.6.2 NESTED LOOPS:


For a pair of nested loops, if 5 tests (MIN, MIN + 1, TYPICAL, MAX – 1, MAX ) need to be done, then there
would be a total of 25 test cases to be run. This number increases with the deep nesting. Testing of all
combinations of nested loops cannot be afforded. The following technique may be used to reduce the number
of test cases --
1. Start at the innermost loop. Set all the outer loops to their minimum values.
2. Test the minimum, maximum+1, typical, maximum-1, and maximum for the innermost loop, while
holding the outer loops at their minimum iteration parameter values.
3. If you’ve done the outermost loop, GOTO step 5, ELSE move out one loop and set it up as in step-2 with
all other loops set to typical values.
4. Continue outward in this manner until all loops have been covered.
5. Do the 5 cases for all loops in the nest simultaneously.

Huang’s twice-through theorem must also be applied to catch data-initialization problems --


1. Hold the outer loops at the minimum values and run the inner loop through its cases.
2. Hold the outer loop at one and run the inner loop through its cases.
3. Finally, hold the outer loop at 2 and run through the inner loop cases. Next, reverse the role of the
inner & outer loop and do it over again.

1.6.3 CONCATENATED LOOPS:


 Two loops are concatenated if it’s possible to reach one after exiting the other while still on a path from
entrance to exit.
 If the loops cannot be on the same path, then they are not concatenated and can be treated as individual
loops.
 Even if the loops are on the same path and if they are independent of each other then treat them as
individual loops. If the iteration values in one loop are directly/indirectly related to the iteration values of
another loop and they can occur on the same path, then treat them as nested loops.

1.6.4 HORRIBLE LOOPS:


The horrible loops are not definitive and are usually too many to execute. To check the end points and
looping values for intertwined loops appears to be unique for each program. The use of code that jumps into
and out of loops, intersecting loops, hidden loops and cross- connected loops, makes iteration value selection
for test cases an awesome. So these structures are avoided.

1.6.5 LOOP TESTING TIME:


Any kind of loop can lead to long testing time, especially while checking for the maximum boundaries. This
situation is worse for nested and concatenated loops. Long test execution times could indicate bugs in the
software or the specification. Consider nested loops in which testing the combination of extreme values leads
to long testing times. There are several options:

1. Show that the combined execution time results from an incorrect specification. Fix the specification.
2. Prove that although the combined extreme time cases are hypothetically possible, they are not
possible in the real world.
3. Put in validation criteria that prevent the combined extreme cases. Test whether validation is working
correctly or not.
4. Test with extreme value combination, but use different numbers. Rescaling technique can be used
where the maximum boundaries can be rescaled to smaller values. For example, if there are 2 nested
loops with maximum boundaries 10000 and 8000 respectively. Then, if we have to test for maximum
boundaries, the running time would be 10000 x 8000 iterations. These boundaries can be rescaled to
100 and 80 respectively and can be tested where the running time would be only 100 x 80 iterations.

1.7 MORE ON TESTING MULTI-ENTRY/MULTI-EXIT ROUTINES:

1.7.1 A WEAK APPROACH:

Suppose we have to test a program that has multi-entry and/or multi-exit routines. An approach to
testing is to create fictitious single-entry segments with fictitious case statements and fictitious processes that
set fictitious exit parameters and go to a fictitious common junction. This fictitious code will help to organize
the test case design. But, this technique involves a lot of extra work. You may not find all the references to
Multi-entry/Multi-exit routines. Missing one case will lead to wrong testing.

This situation can be avoided by presenting the work that has been done to the designer of the
Multi-entry/Multi-exit routine. Discuss with him. He may help in finding out that you have considered wrong
situations or you have missed some references etc. Similarly, every exit destination corresponding to the
pseudo exit parameter should be discussed with the designer of the Multi-exit routine.

BEGIN 1 BEGIN 1 1

BEGIN 2 2

BEGIN N
N

A multi-entry routine is converted to an equivalent single entry routine with an entry parameter and a
controlling case statement.

EXIT 1 1 SET E=1

` EXIT 2 2 SET E=1 EXIT

EXIT N
N
SET E=1
A multi exit routine is converted to an equivalent single exit routine with an exit parameter.

In the assembly language it is possible to calculate the address of the entry point either in absolute
terms or relative to the routines origin. Such multiple entries are truly abominable, because absolute address
calculations make the routines operation dependent upon location, and routines address calculations change
the control flow when the routine is modified.
In some computers, it is not possible to write an interrupt handling routine or device control routine
without resorting to absolute addresses.

1.7.2 THE INTEGRATION TESTING ISSUE:

Treating the multi-entry/exit routine as if it were reasonably structured by using a fictional entry case
statement and a fictional exit parameter is a weak approach because it does not solve the essential testing
problem. Even doing a lot of extra work, it checks only the issues related to individual routines. It does not test
the Multi-entry/Multi-exit routines after they are integrated.

After integrating different components, there will be many callers who may call the Multi-entry/Multi-
exit routine. Different callers may try to enter the routine at different points and may exit from different
points. The essential problem here is an integration testing issue which has to validate different callers.

Valid for caller A, B


Valid for caller A
Multi-entry Components
Valid for caller B, C

In the above figure there is a multi-entry routine with 3 entrances (1, 2, 3 ) and 3 different callers (A,
B, C). The first entrance is valid for callers A & B, the second is valid only for caller A, and the third is valid for
callers B & C. Just testing the entrances doesn’t do the job. In integration testing, it must be assured that caller
A would always enter the routine from entry point 1, caller B would enter the routine either from entry point
2 or 3 etc. Hence, the validity of the call must be established.

Valid for caller A, B


Called by A, B, C Valid for caller A Multi-exit Components
Valid for caller B, C

In the above figure there are 3 exits labeled 1, 2, & 3. It can be called by components A, B or C. Exits 1 & 2 are
valid for the A calls and 1 & 3 are valid for the B calls etc. Component testing must not only confirm that exits
1 & 2 are taken for the A calls, but there are no paths for the A calls that lead to exit 3.

Hence, in integration testing, it must ensure that a caller enters/exits through its valid entry/exit point
and also it does not enter/exit through invalid entry/exit points. When a routine is both Multi-entry and Multi-
exit, then the number of combinations to be tested would be M x N, where M is the number of entries and N
is the numbers of exits.

Multi-Entry/Multi-Exit routines reduce the coding labor, but increase the effort of integration testing.
Inadequate of such routines may introduce unexpected number of bugs into the software.

1.7.3 STRATEGY SUMMARY:

The proper way to test multi-entry/exit routines is:


 Get rid of them.
 Completely control those you can’t get rid of.
 Add to flowgraph input case statements and exit parameters to help you to organize the tests.
 Do stronger unit testing by treating each entry/exit combination as if it were a completely
different routine.
 Recognize that you are dealing with a much more complicated thing than you thought and pay
much more attention in integration testing of such routines.
 Be sure you understand the strategies of automatic test generators and confirm that they do
necessarily work multi-entry/exit routines.

1.8 EFFECTIVENESS OF PATH TESTING:

Approximately 65% of all bugs can be caught in unit testing, which is dominated by path testing methods, of
which statement and branch testing dominates. Statistics show that approximately 35% of all the bugs can be
caught by path testing. Path testing is more effective for unstructured than for structured software. The
statistics also indicate that path testing as a sole technique is limited. The following are reasons:

 Path testing may not cover if you have bugs.


 Path testing may not reveal totally wrong or missing functions.
 Interface errors may not be caught by unit level path testing.
 Database & data flow errors may not be caught.
 The routine can pass its entire test at the unit level, but the possibility that it interferes with other
routines cannot be determined by unit level path tests.
 Not all initialization errors are caught by path testing.
 Specification errors can’t be caught.

2 PREDICATES, PATH PREDICATES & ACHIEVABLE PATHS:

Selecting a path does not mean that it is achievable. Every selected path leads to an associated
boolean expression called the path predicate expression, which characterizes the input values that will cause
that path to be traversed.

2.1 PREDICATES:

The direction taken at a decision depends on the value of decision variables. For binary decisions, decision
processing ultimately results in the evaluation of a logical function whose outcome is either true or false. The
logical function evaluated at decision is called a Predicate.
Ex: A < 0
X + Y > 10
X + Y > 3Z – 44 etc
A predicate associated with a path is called a Path Predicate.

Multi-Way Branches: The path taken through a multi-way branch such as computed GOTO’s, case statements,
or jump tables cannot be directly expressed in TRUE/FALSE terms. The easier way to express multi-way
branches is an equivalent set of IF…. THEN…. ELSE statements.

EX: switch ( X ) if ( X == 1)
{ {
case 1 : ----------- ------------
----------- ------------
case 2 : ----------- }
----------- else
case 3 : ----------- {
----------- if ( X == 2)
} {
------------
------------
}
else
{
----------------
--------------
}
}
The above example shows how a multi-way branching statement can be expressed using two-way branching
statements.
Inputs: In testing, the word input is not restricted to direct inputs, such as variable in a subroutine call, but
includes all data objects referenced by the routine whose values are fixed prior to entering it.
EX: - Inputs in a calling sequence, objects in a data structure values left in a register.
Inputs can be numerical, sets, hash tables, dictionaries, arrays, objects etc. Any array can be mapped onto a
one-dimensional array which we call it as input vector.

2.2 PREDICATE EXPRESSIONS:

2.2.1 PREDICATE INTERPRETATION:

The simplest predicate depends only on input variables.


Ex: X1 & X2 are inputs, the predicate might be X1 + X2 >= 0

Assume that the following piece of code, where the inputs are X1 and X2
--------------
---------------
Y = X2 + 10
----------------
------------------
If ( X1 + Y >= 0 )
-------------

The Y value in the predicate is dependent on processing. But still we can substitute the symbolic expression for
Y to obtain an equivalent predicate X1 + X2 + 10 >= 0.
The act of symbolic substitution of operations along the path in order to express the predicates in terms of the
input vector is called Predicate Interpretation.
EX: --------------
---------------
Y = X1 + 10
----------------
------------------
Z = X2 – 19
------------------
-------------------
If ( Z * Y >= 0 )
-------------
The predicate Z * Y >= 0 can be interpreted as follows –
Z * Y >= 0 (X2 – 19) * Y >= 0 (X2 – 19) * (X1 + 10) >= 0
The final form of predicate after interpretation is solely in terms of constants and inputs.
The interpretation may depend on the path.
EX:

>0 Z = +7

1 X X+Z
Z=0 2 >0
=0

Z = -7
<0
The predicate X + Z > 0 has three interpretations depending upon the path – X + 7 > 0 , X + 0 > 0 , X - 7 > 0

The Path Predicates are the specific form of the predicates of the decisions along the selected path after
interpretation.

2.2.2 INDEPENDENCE & CORRELATION OF VARIABLES & PREDICATES:

The path predicates take on truth values on truth values based on the values of input variables, either directly
or indirectly.

Process Dependent Variable: The variable whose value changes as a result of processing.
Process Independent Variable: The variable whose value does not change as a result of processing.
Process Dependent Predicate: A predicate whose truth value can change as a result of the processing.
Process Independent Predicate: A predicate whose truth value does not change as a result of processing is
process independent.
EX: The input variables are X & Y and the predicate is X + Y = 10.
The processing increments X and decrements Y. Although the numerical values of X & Y are process
dependent, the predicate “ X + Y = 10 ” is process independent.

Variables whether process dependent or independent, may be correlated to one another.


Correlated Variables: Two variables are correlated if every combination of their values cannot be
independently specified.
EX: Two 8-bit variables should lead to 216 combinations. If there is a restriction on their sum like
the sum must be less than or equal to 28 then only 29 combinations are possible.

Uncorrelated Variables: Variables whose values can be specified independently without restriction are
uncorrelated.
Correlated Predicates: A pair of predicates whose outcomes depend on one or more common variables.
Uncorrelated Predicates: A pair of predicates whose outcomes does not depend on one or more common
variables.

2.2.3 PATH PREDICATE EXPRESSION:


 Select an entry/exit path through a routine.
 Write down the un-interpreted predicates for the decisions along the path. If there are loops, be sure
to distinguish each passage through the predicate in the loop. Note the value of the loop variable that
applies to that pass.
 Interpret the predicates to convert them into predicates that contain only input variables. The result is
a set of Boolean expressions, all of which must be satisfied to achieve the selected path. This set is
called the Path Predicate Expression.
Ex: Let the flowgraph be as follows where X is the input

>0 Z = +7

1 X X+Z
=0
Z=0 2 >0
<0
Z = -7
There are 6 paths and hence 6 Path Predicate Expressions --
X > 0 and X + 7 > 0
X > 0 and X + 7 <= 0
X = 0 and X + 0 > 0
X = 0 and X + 0 <= 0
X < 0 and X - 7 > 0
X < 0 and X - 7 <= 0

Let the predicate X > 0 be called as A and X + 7 > 0 as B. The expression X > 0 and X + 7 > 0 can be rewritten as.
The expression X > 0 and X + 7 <= 0 can be rewritten as AB.
The compound predicates ( Ex: X > 7 OR Y < 0 )may lead to the predicate expressions like AB + AC.

Any set of input values that satisfy all the conditions of the path predicate expression will force the execution
through that path. Such path is called as Achievable Path. If there is no such set of inputs, then the path is
called Unachievable Path.
In above example, path X > 0 and X + 7 > 0 is achievable. Any positive value of X will force the execution
through this path. The path X = 0 and X + 0 > 0 is unachievable because if X = 0, then the predicate X + 0 > 0
can never be true. There is no value of X, which can make both the conditions true.

2.3 PREDICATE COVERAGE:

2.3.1 COMPOUND PREDICATES:

Most programming languages permit compound predicates at decisions, i.e., predicates of the form A .OR. B
or A .AND. B and more complicate boolean expressions. The branch taken at such decisions is determined by
the truth value of the entire boolean expression. Even if the decisions predicate is not compound, it may
become compound after interpretation because interpretation may require us to carry forward a compound
term.
Ex: Consider the predicate X > 17. The false path would take the predicate X <= 7, which is equivalent to X < 17
OR X = 17. Here, we did not write a compound predicate, but it became compound after interpretation.

2.3.2 PREDICATE COVERAGE:


Consider a compound predicate such as A + B + C + D (A OR B OR C OR D). It consists of 4 subsidiary predicates,
any of which must be true for the branch to be taken. It’s difficult to predict the sequence in which the
predicates are evaluated because the compiler can rearrange that sequence to optimize the code. Suppose it
evaluates the terms in the order A, B, C, D. If the first term A is true, evaluation stops because the direction of
the branch is determined. Therefore, the desired path could be taken, but there could still be a bug in
predicate B that would not be discovered by this test. If one of the remaining predicates has a bug, then as
they have not been evaluated, they will not be detected. The same situation holds for the predicate such as
ABCD (A AND B AND C AND D). If the predicate A evaluates to false, the compiler will not test the remaining
predicates, because the final result will any way be false.
Hence, it is clear that achieving branch coverage will not be sufficient and a given decision could still
have bugs. Predicate Coverage says that all the predicates in each decision making statement should be
executed at least once. It is achieved if all possible combinations of truth values corresponding to the selected
path have been explored under some test. Predicate coverage is stronger than branch coverage. If all possible
combinations of all predicates under all interpretations are covered then we have the equivalent of total path
testing.

2.4 TESTING BLINDNESS:

Consider the following example:


D1 D2
1 3 4

Here we can reach to decision D2 via the TRUE path or FALSE path of D1. At decision D1, TRUE and FALSE
paths need to be checked. But coming to the second decision D2 is it sufficient to test 2 paths ( TRUE, FALSE of
D2 ) or do we have to test 4 paths ( D1 – TRUE/FALSE D2 – TRUE/FALSE)? There is a need to check 4 paths
because of the situation called as Testing Blindness.

Testing Blindness is a pathological situation in which the desired path is achieved for the wrong reason. It can
occur because of the interaction of 2 or more statements that makes the buggy predicate work. Some of the
kinds of predicate blindness are: Assignment blindness, Equality blindness, and Self blindness.

2.4.1 ASSIGNMENT BLINDNESS:


It occurs when the buggy predicate appears to work correctly because the specific value chosen for an
assignment statement works with both correct and incorrect predicate.
Ex: Correct Buggy
X=7 X=7
……. ………
IF Y > 0 THEN… IF X + Y > 0 THEN …
If the test case sets Y: =1 the desired path is taken in either case, but there is still a bug. Some other path that
leads to the same predicate could have a different assignment value for X, so the wrong path would be taken
because of the error in the predicate.

2.4.2 EQUALITY BLINDNESS:

It occurs when the path selected by a prior predicate results in a value that works both for the correct and
buggy predicate.
Ex: Correct Buggy
IF Y = 2 THEN… IF Y = 2 THEN …
……. ………
IF X + Y > 3 THEN… IF X > 1 THEN …
The first predicate forces the rest of 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 versions.

2.4.3 SELF-BLINDNESS:

It occurs when the buggy predicate is a multiple of the correct predicate and as a result is indistinguishable
along that path.
Ex: Correct Buggy
X=A X=A
……. ………
IF X – 1 > 0 THEN… IF X + A - 2 > 0 THEN …
The assignment makes the predicates multiples of each other, so the direction taken is the same for the
correct and buggy version. A path with another assignment could behave differently and would reveal the
bug.

3 PATH SENSITIZING:

3.1 REVIEW, ACHIEVABLE & UNACHIEVABLE PATHS:

1. We want to select and test enough paths to achieve a satisfactory notion of test completeness (c1/c2).
2. Extract the programs control flow graph and select a set of covering paths.
3. For any path in that set, interpret the predicates along the path as needed to express them in terms of
the input vector.
4. Trace the path through, multiplying the individual compound predicates to achieve a boolean
expression such as,
(A+BC)(D+E)(FGH)(IJ)KL
Where the terms in the parentheses are the compound predicates met at each decision along the path
and each letter (A, B, . . ) stands for simple predicates.
5. Multiply out the expression to achieve a sum-of-products form:
ADFGHIJKL + AEFGHIJKL + BCDFGHIJKL + BCEFGHIJKL
6. Each product term denotes a set of inequalities that if solved will yield an input vector that will drive
the routine along the designated path.
7. Solve any one of the inequality sets for the chosen path and you have found a set of input values for
the path.
If you find a solution, then the path is achievable. If you can’t find a solution to any of the sets
of inequalities, the path is unachievable. The act of finding a set of solutions to the path predicate expression
is called PATH SENSITIZATION.

3.2 HEURISTIC PROCEDURES FOR SENSITIZING PATHS:

Instead of selecting the paths without considering how to sensitize, attempt to choose a covering path set that
is easy to sensitize and pick hard to sensitize paths only to achieve coverage.
1. Identify all variables that affect the decisions. Classify them as to whether they are process
dependent or independent. Identify correlated input variables. Express the dependency and
correlation as an equation, function etc.
2. Classify the predicates as dependent or independent. Identify correlated predicates. Express the
dependency and correlation as an equation, function etc.
3. Start path selection with uncorrelated, independent predicates. If you can achieve coverage and
you had identified dependent predicates, something is wrong. Some of the possibilities are: -
 The predicates are correlated and/or dependent in such a way as to nullify the
dependency.
 The predicates are incorrectly classified. Check your work.
 Your path tracing is faulty. Look for a missing path or incomplete coverage.
 There is a bug.
4. If coverage hasn’t been achieved using independent uncorrelated predicates, extend the path set
by using correlated predicates.
5. If coverage hasn’t been achieved, extend the cases to those that involve dependent predicates,
preferably those that are not correlated.
6. Last, use correlated, dependent predicates.
7. For each path selected above, list the input variables corresponding to the predicates required to
force the path. If the variable is independent, list its value. If the variable is dependent, list the
relation that will make the predicate go the right way. If the variable is correlated, state the nature
of the correlation to other variables.
8. Each path will yield a set of inequalities, which must be simultaneously satisfied to force the path.

3.3 EXAMPLES (FOR SELECTING COVERING PATHS):

3.3.1 SIMPLE, INDEPENDENT, UNCORRELATED PREDICATES:

g
C

a A c
1 A C 5
b C’
A’ d
e
Path Predicate Values
B
Babc A C’
f
abg AC
B’ adec A’ B C’
adeg A’ B C
The uppercase letters in the decision boxes represent the
predicates. The capital letters on adf A’ B’ the links following the decisions
indicate whether the predicate is true or false for that link. Ex: True path for predicate A is indicated as A and
false path is indicated as A’. For 3 decisions, there will be a total possibility of 23 = 8 paths. But the number of
possible paths is only 5 in the above example –

Not all of the above paths need to be tested for providing branch coverage. Only a set of covering paths can
be selected such that all links are covered and all predicates (both true and false paths) are covered.

Path Predicate Values


Covering Paths
abc A C’
abg AC
The above 3 paths would be enough as covering paths and hence these
adeg A’ B C
can be tested to provide branch coverage. Also, the following paths can
be adf A’ B’ chosen, because it is better to start selecting the covering paths by
choosing the simplest one, and continue with small changes to each path.

Covering Paths

3.3.2 CORRELATED, INDEPENDENT PREDICATES:

a A e g
1 A 2 A 3 4
b d A
A’
f
c
A’
Fig: Correlated Decisions

The 2 decisions in the above figure are correlated because they used the identical predicates (A). The paths
abdeg and acdfg are achievable whereas the other 2 paths are unachievable. If the A branch is taken at the
first decision, then A branch must also be taken at the 2nd decision. The flow graph can be replaced with the
below figure, in which we have reproduced the common code into a sub routine.

a A e
1 A 2 5
b d g
3 4
A’
f
2’ 5
c
d

FIG: Correlated Decisions Removed

In general, correlated predicates mean that some paths are not achievable, although this does not mean that
coverage is unachievable. If you select paths from the design flow
Path Predicate Values
graph without considering the details of path sensitization and
subsequently you find that a path is not abc A C’ achievable, even though
it was selected on the basis of meaningful cases, adeg A’ B C then one of the following
must be true: adf A’ B’
 You find a bug.
 The design can be simplified by removing some decisions.
 You have a better understanding of how the decisions are interrelated.
One common and troublesome source of correlated decisions is the reprehensible practice of “saving code”.
Link d in the above example is typical. The designer had thought to save common code.

3.3.3 DEPENDENT PREDICATES:

Loops are the most common kind of dependent predicates, the number of times a typical routine will iterate
in the loop is determined from the input variables values. Consequently, it is easy to work backward to
determine the input value that will force the loop a specified number of times.
3.3.4 THE GENERAL CASE:

There is no simple procedure for the general case. The steps are:
1. Select paths to provide coverage on the basis of functionally sensible paths.
2. Tackle the paths with the fewest decisions first. Give preference to non looping paths over looping
paths.
3. Start at the end of the path and not the beginning. Trace the path in reverse and list the predicates
in the order in which they appear.
4. Continue working backward along the path to the next decision. The next decision may be
restricted by the range of values you determined for the previous decision.
5. Continue until you reach the entrance and therefore have established a set of input conditions for
the entire path.
An alternate approach to use when you are truly faced with functionally sensible paths that require equations
solving to sensitize is a little easier. Let’s say that you have already sensitized some paths and all the rest seem
to be dependent and/or correlated.

1. List the decisions that have yet to be covered in the order in which you expect to traverse them.
For each decision, write down the broadest possible range of input values that affect that
decision.
2. Pick a direction at the first decision on the path that appears to go in the direction you want to go.
3. Continue decision by decision always picking a direction that gets closer to the exit.
4. Assuming that the procedure input values, start a new path using the last decision at which you
had a choice, assuming that such a path will provide additional coverage.

The advantage of the forward method over the backward method is that it’s usually less work to get the input
values because you are solving the simultaneous inequalities as you go. The disadvantage is that you don’t
quite know where you are going.

4 PATH INSTRUMENTATION:

4.1 PROBLEM

The outcome of the test is that what we expect to happen as a result of the test. Test outcomes include
anything like computers memory, mass storage, I/O, registers that should have changed as a result of the test,
or not changed as a result of the test. The expected outcome includes any expected changes or the lack of
change. We predict the outcomes of the test as part of the test design process. We run the test, observe the
actual outcome, and compare that outcome to the expected outcome. If the predicted and actual outcomes
match, can we say that the test has been passed? We cannot. We can only say that some of the necessary
conditions for passing are satisfied, but the conditions are not sufficient because the desired outcome could
have been achieved for the wrong reason. This situation is called coincidental correctness.
X: =16 CASE SELECT Y: =X-14

Y: =2
Fig: Coincidental Correctness
Y: =X/8
Here for the 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
Y: =X coverage.
mod14 Path instrumentation is what we
have to do to conform that the outcome was achieved by the intended path.

4.2 GENERAL STRATEGY:

All instrumentation methods are a variation on a theme of an interpretive trace. An interpretive trace
program is one that executes every statement in order and records the intermediate values of all calculations,
the statement labels traversed etc. If we run the tested routine under a trace, then we have all the
information we need to conform the outcome and to conform 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. Recognizing the limitations of the classical trace
packages or symbolic debuggers, a variety of instrumentation methods have emerged.

4.3 LINK MARKERS

A simple and effective form of instrumentation is called a traversal marker or link marker.

Input A, B, C A>7 [j] B=’a’ [k] C=0 [m]


[p]

[n]
[j]

Fig: Single Link Marker Instrumentation

Name every link by a letter. Instrument the links so that the link’s name is recorded when the link is executed.
A single link marker may not do the trick in some cases. The situation is illustrated in the below figure:

[i] ? [j] PROCESS A PROCESS B

[m]
[k]

PROCESS C ? [n] PROCESS D

Fig: Why single link markers aren’t enough?

We intend to traverse the ikm path, but because of a rampaging GOTO in the middle of the ‘m’ link, we go to
process B. If coincidental correctness is against us, the outcomes will be the same and we won’t know about
the bug. The solution is to implement 2 markers per link: one at the beginning of each link and one at the end
as shown below:

[i] [j] ? [k] PROCESS A PROCESS B [l]

[n] [m]

[o] PROCESS C [p] ? [q] PROCESS [r]


D

The 2 link markers specify the path name and confirm both the beginning and end of the link.

4.4 LINK COUNTERS:

A less informative instrumentation method is based on counters. Instead of a unique link name to be pushed
into a string when the link is traversed, we simply increment a link counter. Put a counter on every link. If
there are no loops, the link counters along the path would be set to 1 after execution. Single link counters
aren’t enough and hence double link counters may be used. The checkout procedure then consists of
answering the following questions:
 Do the begin-link counter values equal the end-link counter values for all links?
 Does the input-link count of every decision equal the sum of the link counts of the output links from
that decision?
 Does the sum of the input-link counts for a junction equal the output link count for that junction?
 Do the counts match the values you predicted when you designed the test?

4.5 OTHER INSTRUMENTATION METHODS:

1. Mark each link by a unique prime number and multiply the link name into a central register. The path
name is a unique number and you can recapture the links traversed by factoring.
2. Use a bit map with a single bit per link and set that bit when the link is traversed.
3. Use a hash coding scheme over the link names and calculate the error detecting code over the link
names such as check sum.
4. User symbolic debuggers to give a trace only of subroutine calls and return.
5. Set a variable value at the beginning of the link to a unique number for that link and use an assertion
statement at the end of the link to conform that you are still on it.

Every instrumentation probe gives you more information. But this hides the location dependent bugs, timing
and race condition bugs. These are peek-a-boo bugs which are really tough.

4.6 IMPLEMENTATION:

Instrumentation is relatively more important when path testing is used at the higher levels of program
structure such as with transaction flows. Path Instrumentation and Verification tools can be used to perform
instrumentation. But, these tools are not available for all languages.
The instrumentation methods like Link Markers, Link Counters etc need the introduction of probes into
the source code. These probes if inserted manually provide new opportunities for bugs. Automatically
inserted probes are less bug-prone.

Inserting more number of probes increases the number of lines of code and hence the compilation
time and execution time. Some programming languages support conditional assembly or conditional
compilation. This facility allows us to specify at the compile time which lines of code need to be compiled and
which parts of code need not be compiled. This can be varied at the time of testing for each test case. We can
compile only those probes which are needed for that particular test case.
Conditional assembly or conditional compilation must be used with caution, especially at higher
program levels. A unit with a set of probes may take a few seconds to compile or assemble. But, if such units
are combined into a component, the number of probes will become very large. Hence, the component may
take some hours for compiling. If conditional assembly or conditional compilations are not available, use
macros or function calls for each category of probe to be implemented. Use functions to either switch on or
off each probe. Use of macros or function calls also reduces the bugs in the probes themselves.
Instrumentation may be installed to verify path testing. It will also be useful in other tests.

5 IMPLEMENTATION AND APPLICATION OF PATH TESTING:

1. Integration, Coverage and Paths in Called Components


 Path testing is mainly used in unit testing.
 An individual unit is first tested by using stubs or drivers. Path testing here helps in identifying the
control flow problems in that unit.
 Then, the unit is combined with its called functions to form a component. The unit is combined with its
functions, one at a time, carefully checking the interfaces. Once the interfaces have been tested, use
path testing on the component.
 Applying path testing for a component has several effects –
o Predicate Interpretation requires us to treat the subroutine as if it were in-line code. This adds
complexity into path testing.
o Path Sensitization becomes more difficult.
o Previously achievable path may now become unachievable.
 The component is now ready for the next level of integration. Integrate this component with another
component and test again (test interfaces and perform path testing).
 This bottom-up integration process continues until the whole system is integrated.
 As components are integrated, there is possibility of more bugs, because some components may be
fully tested and some may have gone through little testing.
 Some branch coverage is lost as we continue with path testing, at higher integration levels. If we
achieve 100% branch coverage at present level, then at the next higher level, we can achieve only 85%
coverage. At the next level we can achieve only 70% and only 60% at the next higher level.

2. New Code
 New Code or modified code should always be subjected to enough path testing.
 Stubs or drivers are used at unit level to perform testing.
 Stubs are replaced with actual functions to form a component and then again path testing is applied.
 When integrating the components, new components need to be rigorously tested. Old and reused
software components can be trusted.
 Path testing becomes difficult and complex at higher level of integration.
 The unit test suite should be mechanized so that it can be repeated as integration progresses.
 Catch and Replay tools can be handy. These tools help to repeat the same tests at each level with less
effort.

3. Maintenance
 The existing software is modified to rectify bugs or to add new features.
 When the code is modified, it has to be tested again irrespective of whether it is a small modification or
large.
 But, now the testing need not use stubs or drivers because the called functions are already available.
 The test cases already available need to be changed to the required extent.
 Path testing is repeated entirely with changed test cases.
 There are differences between new code testing and maintenance testing. Hence, different methods
are needed for new code testing and maintenance testing.

4. Rehosting
 Path testing with C1+C2 coverage is a powerful tool for rehosting old software.
 Rehosting is the process of changing the operating environment of existing software. The change may
be in hardware environment, software environment, language etc.
 Rehosting would be necessary when it is no longer effective to run the software in the existing
environment.
 There are many problems with old software – there will be no documentation available for any process
(documentation of requirements analysis, specifications design, coding, test cases, how to use the
software etc ). Hence, much of its operation is poorly understood. But still the old software has the
greatest advantage that it works correctly. Because the software is used for many years, even if there
were bugs in the software, they are rectified over time. Hence, it would have become bug-free, almost.
 Rehosting can be done in 2 methods
 Rewrite the software from the scratch.
 Develop the software (translator) to convert old code into new code.
 The second methods works as follows – Develop a translator to translate old code into new code. Then,
the old code is tested and the test cases along with the results are documented. The same test cases
(with little changes if needed) are executed on the new code. Such translation may lead to an
inefficient code. But still, this method is advantageous when compared to the first method. It avoids
the risks associated with rewriting the code. Once confidence is achieved, the code can be modified to
improve efficiency.

Anda mungkin juga menyukai