0% found this document useful (0 votes)
42 views26 pages

STM Notes - Unit-5docx

Uploaded by

it.mohan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
42 views26 pages

STM Notes - Unit-5docx

Uploaded by

it.mohan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

Unit-5 Software Testing Methodologies 1

UNIT – 5
STATES, STATE GRAPHS, AND TRANSITION TESTING

The state graph and its associated state table are useful models for describing software
behavior. The finite-state machine is a functional testing tool and testable design programming
tool.

1. MOTIVATIONAL OVERVIEW:
The finite-state machine is as fundamental to software engineering as Boolean algebra.
State testing strategies are based on the use of finite-state machine models for software
structure, software behavior, or specifications of software behavior. Finite-state machines can
also be implemented as table-driven software, in which case they are a powerful design option.
Independent testers are likeliest to use a finite-state machine model as a guide to the design of
functional tests—especially system tests. Software designers are likelier to want to exploit and
test finite-state machine software implementations. Finally, finite-state machine models of
software abound in the testing literature, much of which will be meaningless to readers who don’t
know this subject. Among the affected testing topics are protocols, concurrent systems, system
failure and recovery, system configuration, and distributed data bases

2. STATE GRAPHS
2.1. States
The word “state” is used in much the same way it’s used in ordinary English, as in “state
of the union,” or “state of health.” The Oxford English Dictionary defines “state” as: “A
combination of circumstances or attributes belonging for the time being to a person or thing.”

Fig.11.1 One-Time ZCZC Sequence-Detector state Graph


A program that detects the character sequence “ZCZC” can be in the following states:
1. Neither ZCZC nor any part of it has been detected.
2. Z has been detected.
3. ZC has been detected.
4. ZCZ has been detected.
5. ZCZC has been detected
A moving automobile whose engine is running can have the following states with respect to its
transmission:
1. Reverse gear 2. Neutral gear
3. First gear 4. Second gear
5. Third gear 6. Fourth gear
A person’s checkbook can have the following states with respect to the bank balance:
1. Equal
2. Less than
3. Greater than

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 2

A word processing program menu can be in the following states with respect to file manipulation:
1. Copy document 2. Delete document
3. Rename document 4. Create document
5. Compress document 6. Copy disc
7. Format disc 8. Backup disc
9. Recover from backup

 States are represented by nodes.


 States are numbered or may be identified by words or whatever else is convenient.
 Figure 11.1 shows a typical state graph. The automobile example is really more complicated
because:
(1) the engine might or might not be running,
(2) the car itself might be moving forward or backward or be stopped, and
(3) the clutch might or might not be depressed.
 These factors multiply the above six states by 2 × 3 × 2 = 12, for a total of 72 rather than 6
states. Each additional factor that has alternatives multiplies the number of states in a
model by the number of alternatives
 the number of states, state graphs are most useful for relatively simple functional models
involving at most a few dozen states and only a few factors.

2.2. Inputs and Transitions


Whatever is being modeled is subjected to inputs. As a result of those inputs, the state
changes, or is said to have made a transition. Transitions are denoted by links that join the
states. The input that causes the transition are marked on the link; that is, the inputs are link
weights. There is one outlink from every state for every input. If several inputs in a state cause a
transition to the same subsequent state, instead of drawing a bunch of parallel links.
A finite-state machine is an abstract device that can be represented by a state graph
having a finite number of states and a finite number of transitions between states.
The ZCZC detection example can have the following kinds of inputs:
1. Z
2. C
3. Any character other than Z or C, which we’ll denote by A
The state graph of Figure 11.1 is interpreted as follows:
1. If the system is in the “NONE” state, any input other than a Z will keep it in that state.
2. If a Z is received, the system transitions to the “Z” state.
3. If the system is in the “Z” state and a Z is received, it will remain in the “Z” state. If a C is
received, it will go to the “ZC” state; if any other character is received, it will go back to the
“NONE” state because the sequence has been broken.
4. A Z received in the “ZC” state progresses to the “ZCZ” state, but any other character breaks
the sequence and causes a return to the “NONE” state.
5. A C received in the “ZCZ” state completes the sequence and the system enters the “ZCZC”
state. A Z breaks the sequence and causes a transition back to the “Z” state; any other
character causes a return to the “NONE” state.
6. The system stays in the “ZCZC” state no matter what is received. As you can see, the state
graph is a compact representation of all this verbiage.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 3

2.3. Outputs
 An output can be associated with any link.
 Out puts are denoted by letters or words and are separated from inputs by a slash as follows:
“input/output”.
 As always, output denotes anything of interest that’s observable and is not restricted to explicit
outputs by devices.
 Outputs are also link weights.
 If every input associated with a transition causes the same output, then denoted it as:
“input1, input2, input3…………../output”

Figure 11.2.

The state graph is shown in Figure 11.2. As in the previous example, the inputs and actions have
been simplified. There are only two kinds of inputs (OK, ERROR) and four kinds of outputs (REWRITE,
ERASE, NONE, OUTOF-SERVICE). Don’t confuse outputs with transitions or states.

2.4. State Tables


 Big state graphs are cluttered and hard to follow.
 It’s more convenient to represent the state graph as a table (the state table or state

 Transition table that specifies the states, the inputs, the transitions and the outputs.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 4

 The following conventions are used:


 Each row of the table corresponds to a state.
 Each column corresponds to an input condition.
 The box at the intersection of a row and a column specifies the next state (the transition)
and the output, if any.
2.5. Time versus Sequence
Time:
1. State graphs don’t represent time
2. A transition might take microseconds or centuries; a system could be in one state for
milliseconds and another for eons, or the other way around;
Sequence:
1. State graphs represent sequence.
2. the state graph would be the same because it has no notion of time
Although the finite-state machine model can be elaborated to include notions of time in
addition to sequence, such as timed Petri nets

2.6. Software Implementation


2.6.1. Implementation and Operation
There is rarely a direct correspondence between programs and the behavior of a process
described as a state graph.
The state graph represents, the total behavior consisting of the transport, the software,
the executive, the status returns, interrupts, and so on.
There is no simple correspondence between lines of code and states. The state table forms
the basis.
There are four tables involved:
1. A table or process that encodes the input values into a compact list (INPUT_CODE_TABLE).
2. A table that specifies the next state for every combination of state and input code
(TRANSITION_TABLE).
3. A table or case statement that specifies the output or output code, if any, associated with
every state-input combination (OUTPUT_TABLE).
4. A table that stores the present state of every device or process that uses the same state
table—e.g., one entry per tape transport (DEVICE_TABLE).
The routine operates as follows, where # means concatenation:
BEGIN
PRESENT_STATE := DEVICE_TABLE(DEVICE_NAME)
ACCEPT INPUT_VALUE
INPUT_CODE := INPUT_CODE_TABLE(INPUT_VALUE)
POINTER := INPUT_CODE#PRESENT STATE
NEW_STATE := TRANSITION_TABLE(POINTER)
OUTPUT_CODE := OUTPUT_TABLE(POINTER)
CALL OUTPUT_HANDLER(OUTPUT_CODE)
DEVICE_TABLE(DEVICE_NAME) := NEW_STATE
END

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 5

1. The present state is fetched from memory.


2. The present input value is fetched. If it is already numerical, it can be used directly;
otherwise, it may have to be encoded into a numerical value, say by use of a case statement, a
table, or some other process.
3. The present state and the input code are combined (e.g., concatenated) to yield a pointer
(row and column) of the transition table and its logical image (the output table).
4. The output table, either directly or via a case statement, contains a pointer to the routine to
be executed (the output) for that state-input combination. The routine is invoked (possibly a
trivial routine if no output is required).
5. The same pointer is used to fetch the new state value, which is then stored.

2.6.2. Input Encoding and Input Alphabet


 The alternative to input encoding is a huge state graph and table because there must be one
out link in every state for every possible different input.
 Input encoding compresses the cases and therefore the state graph.
 Another advantage of input encoding is that we can run the machine from a mixture of
otherwise incompatible input events, such as characters, device response codes, thermostat
settings, or gearshift lever positions.
 The set of different encoded input values is called the input alphabet.

2.6.3. Output Encoding and Output Alphabet


There can be many different, incompatible, kinds of outputs for transitions of a finite-
state machine: a single character output for a link is rare in actual applications. We might want
to output a string of characters, call a subroutine, transfer control to a lower-level finite-state
machine, or do nothing. Whatever we might want to do, there are only a finite number of such
distinct actions, which we can encode into a convenient output alphabet.
There are only a finite number of such distinct actions, which we can encode into a
convenient output alphabet.
2.6.3. State Codes and State-Symbol Products

The term state-symbol product is used to mean the value obtained by any scheme used to
convert the combined state and input code into a pointer to a compact table without holes. “state
codes” in the context of finite-state machines, we mean the (possibly) hypothetical integer used
to denote the state and not the actual form of the state code that could result from an encoding
process.

2.6.4. Application Comments for Designers


State-table implementation is advantageous when either the control function is likely to
change in the future or when the system has many similar, but slightly different, control functions.
This technique can provide fast response time—one pass through the above program can
be done in ten to fifteen machine instruction execution times.
It is not an effective technique for very small (four states or less) or big (256 states or
more) state graphs.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 6

2.6.6. Application Comments for Testers

 Independent testers are not usually concerned with either implementation details or the
economics of this approach but with how a state-table or state-graph representation of the
behavior of a program or system can help us to design effective tests.
 There is an interesting correlation, though: when a finite-state machine model is appropriate,
so is a finite-state machine implementation.

4. GOOD STATE GRAPHS AND BAD


4.1. General
What constitutes a good or a bad state graph is to some extent biased by the kinds of
state graphs that are likely to be
used in a software test design
context. Here are some principles
for judging:
1. The total number of states is
equal to the product of the
possibilities of factors that make up
the state.
2. For every state and input there is
exactly one transition specified to
exactly one, possibly the same,
state.
3. For every transition there is one
output action specified. That output
could be trivial, but at least one
output does something sensible.*
4. For every state there is a
sequence of inputs that will drive
the system back to the same state.** Fig 11.3 Improper State Graph

A state graph must have at least two different input codes. With only one input code,
there are only a few kinds of state graphs you can build: a bunch of disconnected individual states;
disconnected strings of states that end in loops and variations thereof; or a strongly connected
state graph in which all states are arranged in one grand loop. The latter can be implemented by a
simple counter that resets at some fixed maximum value, so this elaborate modeling apparatus is
not needed.
The ZCZC detector example didn’t have output codes. There are two aspects of state
graphs: (1) the states with their transitions and the inputs that cause them, and (2) the outputs
associated with transitions. in state testing we may ignore outputs because it is the states and
transitions that are of primary interest.
Two state graphs with identical states, inputs, and transitions could have vastly different
outputs, yet from a state-testing point of view, they could be identical.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 7

4.2. State Bugs


4.2.1. Number of States:
The number of states in a state graph is the number of states we choose to recognize or
model. In practice, the state is directly or indirectly recorded as a combination of values of
variables that appear in the data base. As an example, the state could be composed of the value
of a counter whose possible values ranged from 0 to 9, combined with the setting of two bit flags,
leading to a total of 2 × 2 × 10 = 40 states.
When the state graph represents an explicit state-table implementation, this value is
encoded so bugs in the number of states are less likely; but the encoding can be wrong. Failing to
account for all the states is one of the more common bugs in software that can be modeled by
state graphs. Because an explicit state-table mechanization is not typical, the opportunities for
missing states abound.
Find the number of states as follows:
1. Identify all the component factors of the state.
2. Identify all the allowable values for each factor.
3. The number of states is the product of the number of allowable values of all the factors.

4.2.2. Impossible States


Some combinations of factors may appear to be impossible. Say that the factors are:
GEAR R, N, 1, 2, 3, 4 = 6 factors
DIRECTION Forward, reverse, stopped = 3 factors
ENGINE Running, stopped = 2 factors
TRANSMISSION Okay, broken = 2 factors
ENGINE Okay, broken = 2 factors
TOTAL = 144 states
But broken engines can’t run, so the combination of factors for engine condition and
engine operation yields only 3 rather than 4 states. Therefore, the total number of states is at
most 108. A car with a broken transmission won’t move for long, thereby further decreasing the
number of feasible states.
The discrepancy between the programmer’s state count and the tester’s state count is
often due to a difference of opinion concerning “impossible states.”

4.2.3. Equivalent States


Two states are equivalent if every sequence of inputs starting from one state produces
exactly the same sequence of outputs
when started from the other state. This
notion can also be extended to sets of
states. Figure 11.4 shows the situation.
Say that the system is in state
S and that an input of causes a
transition to state a while an input of b
Fig 11.4 Equivalent States

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 8

causes a transition to state B. The blobs


indicate portions of the state graph whose
details are unimportant.

Fig 11.5 Equivalent States of Fig 11.4 Merged


If, starting from state A, every possible sequence of inputs produces exactly the same
sequence of outputs that would occur when starting from state B, then there is no way that an
outside observer can determine which of the two sets of states the system is in without looking at
the record of the state.
The state graph can be reduced to that of Figure 11.5 without harm
Equivalent states can be recognized by the
following procedures:
1. The rows corresponding to the two states
are identical with respect to
input/output/next state but the name of
the next state could differ. The two states
are differentiated only by the input that
distinguishes between them. This situation
is shown in Figure 11.6. Except for the a,b
inputs, which distinguish between states A
and B, the system’s behavior in the two
states is identical for every input sequence;
they can be merged. Fig 11.6 Equivalent
states
2. There are two sets of rows which, except for the state names, have identical state graphs with
respect to transitions and outputs. The two sets can be merged (see Figure 11.7).

The rows are not identical, but except for the state names (A1 = B2, A2 = B2, A3 = B3), the
system’s action, when judged by the relation between the output sequence produced by a given
input sequence, is identical for either the A or the B set of states. Consequently, this state graph
can be replaced by the simpler version shown in Figure 11.7c.

4.3. Transition Bugs


4.3.1. Unspecified and Contradictory Transitions
Exactly one transition must be specified for every combination of input and state. However you model it
or test it, the system will do something for every combination of input and state. It’s better that it does
what you want it to do, which you assure by specifying a transition rather than what some bugs want it to
do.
A program can’t have contradictions or ambiguities. Ambiguities are impossible because
the program will do something (right or wrong) for every input. Even if the state does not change,
by definition this is a transition to the same state. Similarly, software can’t have contradictory
transitions because computers can only do one thing at a time.

4.3.2. An Example
Specifications are one of the most common sources of ambiguities and contradictions.
Specifications, unlike programs, can be full of ambiguities and contradictions. The following
example illustrates how to convert a specification into a state graph and how contradictions can

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 9

come about. The tape control routine will be used. Start with the first statement in the
specification and add to the state graph one statement at a time.
Here is the first statement of the specification:

There are only two input values, “okay” and “error.” A state table will be easier to work
with, and it’s much easier to spot ambiguities and contradictions. Here’s the first state table:
There are only two input values, “okay” and “error.”

STATE OKAY ERROR


0 0/none 1/
1 2/
2 3/
3 4/
4 5/
5 6/
6 7/
7 8/

There are no contradictions yet, but lots of ambiguities. It’s easy to see how ambiguities come
about—just stop the specification before it’s finished. Let’s add the rules one at a time and fill in the state
graph as we go. Here are the rest of the rules; study them to see if you can find the problems, if any:
Rule 2: If there is an error, rewrite the block.
Rule 3: If there have been three successive errors, erase 10 centimeters of tape and then
rewrite the block.
Rule 4: If there have been three successive erasures and another error occurs, put the unit out
of service.
Rule 5: If the erasure was successful, return to the normal state and clear the error counter.
Rule 6: If the rewrite was unsuccessful, increment the error counter, advance the state, and try
another rewrite.
Rule 7: If the rewrite was successful, decrement the error counter and return to the previous
state.
Adding rule 2, we get
STATE OKAY ERROR

0 0/NONE 1/REWRITE
01 2/Rewrite
3 3/Rewrite
4 4/Rewrite
5 5/Rewrite
6 6/Rewrite
7 7/Rewrite

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 10

Rule 3: If there have been three successive errors, erase 10 centimeters of tape and then
rewrite the block.
INPUT
STATE OKAY ERROR
0 0/NONE 1/REWRITE
1 2/REWRITE
2 3/REWRITE, ERASE, REWRITE
3 4/REWRITE, ERASE, REWRITE
4 5/REWRITE, ERASE, REWRITE
5 6/REWRITE, ERASE, REWRITE
6 7/REWRITE, ERASE, REWRITE
7 8/REWRITE, ERASE, REWRITE
Rule 3, if followed blindly, causes an unnecessary rewrite. It’s a minor bug, so let it go for now, but
it pays to check such things. There might be an arcane security reason for rewriting, erasing, and
then rewriting again.
Rule 4: If there have been three successive erasures and another error occurs, put the unit out of
service.
INPUT
STATE OKAY ERROR
0 0/NONE 1/RW
1 2/RW
2 3/ER, RW
3 4/ER,RW
4 5/ER, RW
5 6/OUT
6
7

Rule 4 terminates our interest in this state graph so we can dispose of states beyond 6. The
details of state 6 will not be covered by this specification; presumably there is a way to get back to
state 0. Also, we can credit the specifier with enough intelligence not to have expected a useless
rewrite and erase prior to going out of service
Rule 5: If the erasure was successful, return to the normal state and clear the counter.

Rule 6: If the rewrite was unsuccessful, increment the error counter, advance the state,
and try another rewrite. Because the value of the error counter is the state, and because rules I
and 2 specified the same action, there seems to be no point to rule 6 unless yet another rewrite
was wanted. Furthermore, the order of the actions is wrong. If the state is advanced before the
rewrite, we could end up in the wrong state. The proper order should have been: output =
attempt-rewrite and then increment the error counter.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 11

Rule 7: If the rewrite was successful, decrement the error counter and return to the
previous state.

Rule 7 got rid of the ambiguities but created contradictions. The specifier’s intention was probably:
Rule 7A: If there have been no erasures and the rewrite is successful, return to the previous state.

4.3.3. Unreachable States An unreachable state is like unreachable code—a state that no input sequence
can reach. An unreachable state is not impossible, just as unreachable code is not impossible. Furthermore,
there may be transitions from the unreachable state to other states; there usually are because the state
became unreachable as a result of incorrect transitions.
Unreachable states can come about from previously “impossible” states. You listed all the
factors and laid out a state table. Some of these states corresponded to previously “impossible” states. The
designer, perhaps after some rough persuasion, agrees that something should be done about the
unreachable states. “Easy,” he thinks, “provide no transitions into them.” Yet there should still be a
transition out of all such states. At least there should be a transition to an error-recovery procedure or an
exception handler.
An isolated, unreachable state here and there, which clearly relates to impossible combinations
of real-world state determining conditions, is acceptable, but if you find groups of connected states that
are isolated from others, there’s cause for concern.
There are two possibilities:
(1) There is a bug; that is, some transitions are missing.
(2) The transitions are there, but you don’t know about it; in other words, there are other
inputs and associated transitions to reckon with. Typically, such hidden transitions are caused by software
operating at a higher priority level or by interrupt processing.

4.3.4. Dead States


A dead state, (or set of dead states) is a state that once entered cannot be left. This is not
necessarily a bug, but it is suspicious. If the software was designed to be the fuse for a bomb, we would
expect at least one such state.
A set of states may appear to be dead because the program has two modes of operation. In the
first mode it goes through an initialization process that consists of several states. Once initialized, it goes to
a strongly connected set of working states, which, within the context of the routine, cannot be exited.
The initialization states are unreachable to the working states, and the working states are dead
to the initialization states. The only way to get back might be after a system crash and restart. Legitimate
dead states are rare. They occur mainly with system-level issues and device handlers. In normal software, if
it’s not possible to get from any state to any other, there’s reason for concern

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 12

4.4. Output Errors


The states, the transitions, and the inputs could be correct, there could be no dead or
unreachable states, but the output for the transition could be incorrect. Output actions must be verified
independently of states and transitions.
That is, you should distinguish between a program whose state graph is correct but has the
wrong output for a transition and one whose state graph is incorrect. The likeliest reason for an incorrect
output is an incorrect call to the routine that executes the output. This is usually a localized and minor bug.
Bugs in the state graph are more serious because they tend to be related to fundamental control-structure
problems. If the routine is implemented as a state table, both types of bugs are comparably severe.
4.5. Encoding Bugs:
It would seem that encoding bugs for input coding, output coding, state codes, and state-symbol product
formation could exist as such only in an explicit finite-state machine implementation. The possibility of
such bugs is obvious for a finite-state machine implementation, but the bugs can also occur when the
finite-state machine is implicit.
If the programmer has a notion of state and has built an implicit finite-state machine, say by
using a bunch of program flags, switches, and “condition” or “status” words, there may be an encoding
process in place. Make it a point not to use the programmer’s state numbers and/or input codes. As a
tester, you’re dealing with an abstract machine that you’re going to use to develop tests. The behavior of a
finite-state machine is invariant under all encodings.
That is, say that the states are numbered 1 to n. If you renumber the states by an arbitrary
permutation, the finite-state machine is unchanged—similarly for input and output codes. Therefore, if you
present your version of the finite-state machine with a different encoding, and if the programmer objects
to the renaming or claims that behavior is changed as a result, then use that as a signal to look for
encoding bugs.
You may have to look at the implementation for these, especially the data dictionary. Look for
“status” codes and read the list carefully. The key words are “unassigned,” “reserved,” “impossible,”
“error,” or just gaps. The implementation of the fields as a bunch of bits or bytes tells you the potential size
of the code. If the number of code values is less than this potential, there is an encoding process going on,
even if it’s only to catch values that are out of range. In strongly typed languages with user-defined
semantic types, the encoding process is probably a type conversion from a set membership, say, to a
pointer type or integer. Again, you may have to look at the program to spot potential bugs of this kind.

5. State testing
5.1. Impact of Bugs
Let’s say that a routine is specified as a state graph that has been verified as correct in all
details. Program code or tables or a combination of both must still be implemented. A bug can
manifest itself as one or more of the following symptoms:
1. Wrong number of states.
2. Wrong transition for a given state-input combination.
3. Wrong output for a given transition.
4. Pairs of states or sets of states that are inadvertently made equivalent (factor lost).
5. States or sets of states that are split to create inequivalent duplicates.
6. States or sets of states that have become dead.
7. States or sets of states that have become unreachable
5.2. Principles
The strategy for state testing is analogous to that used for path-testing flowgraphs. Just as
it’s impractical to go through every possible path in a flowgraph, it’s impractical to go through
every path in a state graph. A path in a state graph, of course, is a succession of transitions caused
by a sequence of inputs.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 13

The notion of coverage is identical to that used for flowgraphs—pass through each link
(i.e., each transition must be exercised). Assume that some state is especially interesting—call it
the initial state. Because most realistic state graphs are strongly connected, it should be possible
to go through all states and back to the initial state, when starting from there. But don’t do it.
Even though most state testing can be done as a single case in a grand tour, it’s impractical to do
it that way for several reasons:
1. In the early phases of testing, you’ll never complete the grand tour because of bugs.
2. Later, in maintenance, testing objectives are understood, and only a few of the states and
transitions have to be retested. A grand tour is a waste of time.
3. There’s so much history in a long test sequence and so much has happened that verification
is difficult.
The starting point of state testing is:
1. Define a set of covering input sequences that get back to the initial state when starting
from the initial state.
2. For each step in each input sequence, define the expected next state, the expected
transition, and the expected output code.
A set of tests, then, consists of three sets of sequences:
1. Input sequences.
2. Corresponding transitions or next-state names.
3. Output sequences.
5.3. Limitations and Extensions
Just as link coverage in a flow graph model of program behavior did not guarantee “complete
testing,” state transition coverage in a state-graph model does not guarantee complete testing.
Things are slightly better because it’s not necessary to consider any sequence longer than the
total number of states.
A hierarchy of paths and methods for combining paths to produce covers of a state graph. The
simplest is called a “0 switch,” which corresponds to testing each transition individually. The next
level consists of testing transition sequences consisting of two transitions, called “1 switch.” The
maximum-length switch is an n – 1 switch, where n is the number of states.
Primary result shows that in general, a 0 switch cover (which we recognize as branch cover for
control flow graphs) can catch output errors but may not catch some transition errors. In general,
one must use longer and longer covering sequences to catch transition errors, missing states,
extra states, and the like. The theory of what constitutes a sufficient number of tests (i.e., input
sequences) to catch specified kinds of state-graph errors is still in its infancy. Furthermore,
practical experience with the application of such theory to software as exists is limited, and the
efficacy of such methods as bug catchers has yet to be demonstrated sufficiently well to earn
these methods a solid place in the software tester’s tool repertoire. Work continues and progress
in the form of semiautomatic test tools and effective methods are sure to come.
Meanwhile, we have the following experience:
1. Simply identifying the factors that contribute to the state, calculating the total number of states, and
comparing this number to the designer’s notion catches some bugs.
2. Insisting on a justification for all supposedly dead, unreachable, and impossible states and transitions
catches a few more bugs.
3. Insisting on an explicit specification of the transition and output for every combination of input and
state catches many more bugs.
4. A set of input sequences that provide coverage of all nodes and links is a mandatory minimum
requirement.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 14

5. In executing state tests, it is essential that means be provided (e.g., instrumentation software) to
record the sequence of states (e.g., transitions) resulting from the input sequence and not just the
outputs that result from the input sequence.

5.4. What to Model


The state graph is a behavioral model—it is functional rather than structural and is thereby
far removed from the code. As a testing method, it is a bottom-line method that ignores structural
detail to focus on behavior. It is advantageous to look into the database to see how the factors
that create the states are represented in order to get a state count.
More than most test methods, state testing yield the biggest payoffs during the design of
the tests rather than during the running thereof. Because the tests can be constructed from a
design specification long before coding, they help catch deep bugs early in the game when
correction is inexpensive.
Here are some situations in which state testing may prove useful:
1. Any processing where the output is based on the occurrence of one or more sequences of
events, such as detection of specified input sequences, sequential format validation, parsing,
and other situations in which the order of inputs is important.
2. Most protocols between systems, between humans and machines, between components of a
system (CHOI84, CHUN78, SARI88).
3. Device drivers such as for tapes and discs that have complicated retry and recovery
procedures if the action depends on the state.
4. Transaction flows where the transactions are such that they can stay in the system
indefinitely—for example, online users, tasks in a multitasking system.
5. High-level control functions within an operating system. Transitions between user states,
supervisor’s states, and so on. Security handling of records, permission for read/write/modify
privileges, priority interrupts and transitions between interrupt states and levels, recovery
issues and the safety state of records and/or processes with respect to recording recovery
data.
6. The behavior of the system with respect to resource management and what it will do when
various levels of resource utilization are reached. Any control function that involves responses
to thresholds where the system’s action depends not just on the threshold value, but also on
the direction in which the threshold is crossed. This is a normal approach to control functions.
A threshold passage in one direction stimulates a recovery function, but that recovery function
is not suspended until a second, lower threshold is passed going the other way.
7. A set of menus and ways that one can go from one to the other. The currently active menus
are the states, the input alphabet is the choices one can make, and the transitions are
invocations of the next menu in a menu tree. Many menu-driven software packages suffer
from dead states—menus from which the only way out is to reboot.
8. Whenever a feature is directly and explicitly implemented as one or more state-transition
tables

5.5 Getting the Data

As is so often the case in the independent tester’s life, getting the data on which the model
is to be based is half the job or more. There’s no magic for doing that: reading documents,
interviews, and all the rest. State testing, more than most functional test strategies, tends to have
a labor-intensive data-gathering phase and tends to need many more meetings to resolve issues.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 15

This is the case because most of the participants don’t realize that there’s an essential
state-machine behavior. For nonprogrammers, especially, the very concept of finite-state machine
behavior may be missing. Be prepared to spend more time on getting data than you think is
reasonable and be prepared to do a lot of educating along the way.
5.6. Tools
Good news and bad news: The telecommunications industry, especially in telephony, has
been using finite-state machine implementations of control functions for decades. They also use
several languages/systems to code state tables directly. Similarly, there are tools to do the same
for hardware logic designs. That’s the good news.
The bad news is that these systems and languages are proprietary, of the home-brew
variety, internal, and/or not applicable to the general use of software implementations of finite-
state machines. The most successful tools are not published and are unlikely to be published
because of the competitive advantage they give to the users of those tools.

6. TESTABILITY TIPS
6.1. A Balm for Programmers
 The key to testability design is easy: build explicit finite-state machines.
6.2. How Big, How Small?
There are about eighty possible good and bad three-state machines,
 2700 four-state machines,
 275,000 five-state machines, and
 Close to 100 million six-state machines, most of which are bad

6.3. Switches, Flags, and Unachievable Paths


Something may look like a finite-
state machine but not be one.
Figure 11.9a shows a program with a switch
or flag. Someplace early in the routine we set
a flag, A, then later we test the flag and go
one way or the other depending on its value.
In Figure 11.9b we’ve rewritten the routine to
eliminate the flag. As soon as the flag value is
calculated, we branch.
The cost is the cost of converting
segment V into a subroutine and calling it
twice. But note that we went from four Figure 11.9
paths, two of which are unachievable to two
paths, both of which are achievable and both of which are needed to achieve branch coverage.
In Figure 11.10, the situation is more complicated. There are three switches this time. Again,
where we go depends on the switch settings calculated earlier in the program. We can put the decision up
front and branch directly, and again use subroutines to make each path explicit and do without the
switches. The advantages of this implementation are that if any of the combinations are not needed, we
merely clip out that part of the decision tree, as in Figure 11.10c. Again, all paths are achievable and all
paths are needed for branch cover.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 16

Figure 11.11 is
similar to the previous
two except that we’ve
put the switched parts
in a loop. It’s even
worse if the loop
includes the switch
value calculations
(dotted link).

figure 11.10
We now have a
very difficult situation.
We don’t know which of
these paths are
achievable and which
are or are not required.
What is or is not
achievable depends on
the switch settings.
Branch coverage
won’t do it: we must do
or attempt branch
coverage in every possible state.

6.4. Essential and Inessential Finite-State Behavior


The simplest essential finite-state machine is a flip-flop. There is no logic that can implement it
without some kind of feedback. we cannot describe this behavior by a decision table or decision tree
unless you provide feedback into the table or call it recursively.

figure 11.11

6.5. Design Guidelines

Assume that you’ve checked the design and the specification and that you’re not about to
implement inessential finite-state machine behavior. What should you do if you must build finite-state
machines into your code?

1. Start by designing the abstract machine. Verify that it is what you want to do. Do an explicit
analysis, in the form of a state graph or table, for anything with three states or more.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 17

2. Start with an explicit design—that is, input encoding, output encoding, state code assignment,
transition table, output table, state storage, and how you intend to form the state-symbol product.
Do this at the PDL level. But be sure to document that explicit design.
3. Before you start taking shortcuts, see if it really matters. Neither the time nor the memory for the
explicit implementation usually matters
4. Take shortcuts by making things implicit only as you must to make significant reductions in time or
space and only if you can show that such savings matter in the context of the whole system.
After all, doubling the speed of your implementation may mean nothing if all you’ve done is
shaved 100 microseconds from a 500-millisecond process. The order in which you should make
things implicit are: output encoding, input encoding, state code, state-symbol product, output
table, transition table, state storage. That’s the order from least to most dangerous.
5. Consider a hierarchical design if you have more than a few dozen states.
6. Build, buy, or implement tools and languages that implement finite-state machines as software if
you’re doing more than a dozen states routinely.
7. Build in the means to initialize to any arbitrary state. Build in the transition verification
instrumentation (the coverage analyzer). These are much easier to do with an explicit machine.

GRAPH MATRICES AND APPLICATIONS

1. SYNOPSIS
Graph matrices are introduced as another representation for graphs; some useful tools
resulting therefrom are examined. Matrix operations, relations, node-reduction algorithm
revisited, equivalence class partitions

2. MOTIVATIONAL OVERVIEW
2.1. The Problem with Pictorial Graphs
Whenever a graph is used as a model, sooner or later we trace paths through it—to find a set of
covering paths, a set of values that will sensitize paths, the logic function that controls the flow, the
processing time of the routine, the equations that define a domain, whether the routine pushes or pops, or
whether a state is reachable or not.
Even algebraic representations such as BNF and regular expressions can be converted to equivalent
graphs. Much of test design consists of tracing paths through a graph and most testing strategies define
some kind of cover over some kind of graph.
• To find a set of covering paths, a set of values that will sensitize paths, the logic function
that controls the flow, the processing time of the routine, the equations that define a
domain, whether the routine pushes or pops, or whether a state is reachable or not.
• One solution to this problem is to represent the graph as a matrix and to use matrix
operations equivalent to path tracing.
2.2. Tool Building
• The properties of graph matrices are fundamental to test tool building.
2.3. Doing and Understanding Testing Theory
• we prove theorems about graphs by proving theorems about their matrix representations.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 18

• Without the conceptual apparatus of graph matrices, you’ll be blind to much of testing
theory, especially those parts that lead to useful algorithms.
2.4. The Basic Algorithms
The basic toolkit consists of:
• Matrix multiplication, which is used to get the path expression from every node to every
other node.
• A partitioning algorithm for converting graphs with loops into loop-free graphs of
equivalence classes.
• A collapsing process (analogous to the determinant of a matrix), which gets the path
expression from any node to any other node.

3. THE MATRIX OF A GRAPH


3.1. Basic Principles
A graph matrix is a square array with one row and one column for every node in the graph. Each
row-column combination corresponds to a relation between the node
corresponding to the row and the node corresponding to the column. The
relation, for example, could be as simple as the link name, if there is a link
between the nodes.
Some examples of graphs and their associated matrices are
shown in Figure 12. 1 a through g. Observe the following:
1. size of the matrix (i.e., the number of rows and columns) equals the
number of nodes.
2. There is a place to put every possible direct connection or link between
any node and any other node.
3. The entry at a row and column intersection is the link weight of the link
(if any) that connects the two nodes in that direction.
4. A connection from node i to node j does not imply a connection from
node j to node i. Note that in Figure 12.1h the (5,6) entry is m, but the (6,5) entry is c.
5. If there are several links between two nodes, then the entry is a sum;
the “+” sign denotes parallel links as usual. Figure 12.1
An entry is not just a simple link name but a path expression
corresponding to the paths between the pair of nodes.
In general, an entry is not just a simple link name but a path
expression corresponding to the paths between the pair of nodes.
Furthermore, as with the graphs, an entry can be a link weight or an expression in link weights. Finally,
“arithmetic operations” are the operations appropriate to the weights the links represent.
3.2. A Simple Weight
The simplest weight we can use is to note that there is or isn’t a connection. Let “1” mean that there is
a connection and “0” that there isn’t.
The arithmetic rules are:
1 + 1 = 1, 1 + 0 = 1,
0 + 0 = 0, 1 × 1 = 1,
1 × 0 = 0, 0 × 0 = 0.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 19

Figure 12.1 g,h,i

A matrix with weights defined like this is called a connection matrix. The connection matrix for Figure
12.1h is obtained by replacing each entry with I if there is a link and 0 if there isn’t. As usual, to reduce
clutter we don’t write down 0 entries.
Each row of a matrix (whatever the weights) denotes the out links of the node corresponding to that
row, and each column denotes the in links corresponding to that node. A branch node is a node with more
than one nonzero entry in its row. A junction node is a node with more than one nonzero entry in its
column.
A self-loop is an entry along the diagonal. Because rows 1, 3, 6, and 8 of Figure 12.1h all have more than
one entry, those nodes are branch nodes. Using the principle that a case statement is equivalent to n – 1
binary decisions, by subtracting 1 from the total number of entries in each row and ignoring rows with no
entries (such as node 2), we obtain the equivalent number of decisions for each row. Adding these values
and then adding I to the sum yields the graph’s cyclamate complexity
3.3. Further Notation
The path segments expressed in terms of link names and, in this notation, for several paths in
the graph of Figure 12.1h are:
• abmd = a13a35a56a67;
• degef = a67a78a87a78a82;
• ahekmlld = a13a37a78a85a56a66a66a67;
Because a13 = a, a35 = b, a56 = m, a66 = l, a67 = d, etc.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 20

• The transpose of a matrix is the matrix with rows and columns interchanged. It is denoted
by a superscript letter “T,” as in AT.
• The intersection of two matrices of the same size, denoted by A#B is a matrix obtained by
an element-by-element multiplication operation on the entries. For example, C = A#B
means cij = aij#bij.
• The multiplication operation is usually boolean AND or set intersection. Similarly, the union
of two matrices is defined as the element-by-element addition operation such as a boolean
OR or set union.

4. RELATIONS
4.1. General
A relation is a property that exists between two (usually) objects of interest.
1. “Node a is connected to node b” or aRb where “R” means “is connected to.”
2. “a >= b” or aRb where “R” means “greater than or equal.”
3. “a is a subset of b” where the relation is “is a subset of.”
4. “It takes 20 microseconds of processing time to get from node a to node b.” The relation is
expressed by the number 20.
5. “Data object X is defined at program node a and used at program node b.” The relation
between nodes a and b is that there is a du chain between them.
Graph consists of a set of abstract objects called nodes and a relation R between the
nodes. If aRb, which is to say that a has the relation R to b, it is denoted by a link from a to b. In
addition to the fact that the relation exists, for some relations we can associate one or more
properties. These are called link weights.
A link weight can be numerical, logical, illogical, objective, subjective, or whatever.
Furthermore, there is no limit to the number and type of link weights that one may associate with
a relation. “Is connected to” is just about the simplest relation there is: it is denoted by an
unweighted link. Graphs defined over “is connected to” are called, as we said before, connection
matrices. * For more general relations, the matrix is called a relation matrix.

4.2. Properties of Relations


• Relations are that there be an algorithm by which we can determine whether or not the
relation exists between two nodes.
4.2.1. Transitive Relations
 A relation R is transitive if aRb and bRc implies aRc.Most relations used in testing are
transitive.
 Examples of transitive relations include:
is connected to, is greater than or equal to, is less than or equal to, is a relative of, is faster
than, is slower than, takes more time than, is a subset of, includes, shadows, is the boss of.
 Examples of intransitive relations include:
is acquainted with, is a friend of, is a neighbor of, is lied to, has a du chain between
4.2.2. Reflexive Relations
• A relation R is reflexive if, for every a, aRa. A reflexive relation is equivalent to a self-loop at
every node.
• Examples of reflexive relations include: equals, is acquainted with (except, perhaps, for
amnesiacs), is a relative of.

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 21

• Examples of irreflexive relations include: not equals, is a friend of (unfortunately), is on top of,
is under.
4.2.3. Symmetric Relations
 A relation R is symmetric if for every a and b, aRb implies bRa.
 A symmetric relation means that if there is a link from a to b then there is also a link from b to
a; which furthermore means that we can do away with arrows and replace the pair of links with
a single undirected link.
 A graph whose relations are not symmetric is called a directed graph because we must use
arrows to denote the relation’s direction. A graph over a symmetric relation is called an
undirected graph.
 * The matrix of an undirected graph is symmetric (aij = aji for all i, j).
 Examples of symmetric relations:
is a relative of, equals, is alongside of, shares a room with, is married (usually), is brother of, is
similar (in most uses of the word), OR, AND, EXOR.
 Examples of asymmetric relations:
is the boss of, is the husband of, is greater than, controls, dominates, can be reached from.
4.2.4. Antisymmetric Relations
 A relation R is antisymmetric if for every a and b, if aRb and bRa, then a = b, or they are the same
elements.
 Examples of antisymmetric relations:
is greater than or equal to, is a subset of, time.
 Examples of nonantisymmetric relations:
is connected to, can be reached from, is greater than, is a relative of, is a friend of.

4.3. Equivalence Relations


• An equivalence relation is a relation that satisfies the reflexive, transitive, and symmetric
properties.
• Numerical equality is the most familiar example of an equivalence relation.
• If a set of objects satisfy an equivalence relation, we say that they form an equivalence class
over that relation.
• The idea behind partition-testing strategies such as domain testing and path testing, is that
we can partition the input space into equivalence classes.

5. THE POWERS OF A MATRIX


5.1. Principles
Each entry in the graph’s matrix (that is, each link) expresses a relation between the
pair of nodes that corresponds to that entry. It is a direct relation, but we are usually interested
in indirect relations that exist by virtue of intervening nodes between the two nodes of
interest. Squaring the matrix (using suitable arithmetic for the weights) yields a new matrix
that expresses the relation between each pair of nodes via one intermediate node under the
assumption that the relation is transitive. The square of the matrix represents all path

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 22

segments two links long. Similarly, the third power represents all path segments three links
long. And the kth power of the matrix represents all path segments k links long. Because a
matrix has at most n nodes, and no path can be more than n – 1 links long without
incorporating some path segment already accounted for, it is generally not necessary to go
beyond the n – 1 power of the matrix. As usual, concatenation of links or the weights of links is
represented by multiplication, and parallel links or path expressions by addition.
Let A be a matrix whose entries are aij. The set of all paths between any node i and any
other nodej (possiblyiitself), via all possible intermediate nodes, is given by
As formidable as this expression might appear, it states nothing more than the
following:

1. Consider the relation between every node and its neighbor.


2. Extend that relation by considering each neighbor as an intermediate node.
3. Extend further by considering each neighbor’s neighbor as an intermediate node.
4. Continue until the longest possible nonrepeating path has been established.
5. Do this for every pair of nodes in the graph.

5.2. Matrix Powers and Products


Given a matrix whose entries are aij, the square of that matrix is obtained by replacing every entry with.

More generally, given two matrices A and B, with entries aik and bkj, respectively, their product is a new
matrix C, whose entries are cij, where:

The indexes of the product [e.g.,


(3,2) in C32] identify, respectively, the row of
the first matrix and the column of the second
matrix that will be combined to yield the entry
for that product in the product matrix. The C32
entry is obtained by combining, element by
element, the entries in the third row of the A
matrix with the corresponding elements in the
second column of the B matrix

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 23

Applying this to the matrix of Figure 12.1g yields

A 2A = AA2 ; that is, matrix multiplication is associative (for most interesting relations) if the
underlying relation arithmetic is associative. Therefore, you can get A4 in any of the following ways: A2A 2 ,
(A2 ) 2 , A3A, AA3 .
However, because multiplication is not necessarily commutative, you must remember to put the
contribution of the left-hand matrix in front of the contribution of the right-hand matrix and not
inadvertently reverse the order.
The loop terms are important. These are the terms that appear along the principal diagonal (the
one that slants down to the right). The initial matrix had a self-loop about node 5, link h. No new loop is
revealed with paths of length 2, but the cube of the matrix shows additional loops about nodes 3 (bfe), 4
(feb), and 5 (ebf). It’s clear that these are the same loop around the three nodes.

5.3. The Set of All Paths


• To use matrix operations to obtain the set of all paths between all nodes or, equivalently, a
property (described by link weights) over the set of all paths from every node to every other
node, using the appropriate arithmetic rules for such weights.
• The set of all paths between all nodes is easily expressed in terms of matrix operations. It’s
given by the following infinite series of matrix powers:

This is an eloquent, but practically useless, expression. Let I be an n by n matrix, where n is the
number of nodes. Let I’s entries consist of multiplicative identity elements along the principal
diagonal. For link names, this can be the number “1.” For other kinds of weights, it is the
multiplicative identity for those weights. The above product can be re-phrased as:
A(I + A + A2 + A3 + A4 . . . A∞ )
But often for relations, A + A = A, (A + I)2 = A2 + A +A + I A2 + A + I. Furthermore, for any finite n,
(A + I)n = I + A + A2 + A3 . . . An
Therefore, the original infinite sum can be replaced by

Ai = A(A+I)n

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 24

This is an improvement, because in the original expression we had both infinite products and
infinite sums, and now we have only one infinite product to contend with. The above is valid
whether or not there are loops. If we restrict our interest for the moment to paths of length n – 1,
where n is the number of nodes, the set of all such paths is given by

This is an interesting set of paths because, with n nodes, no path can exceed n – 1
nodes without incorporating some path segment that is already incorporated in some other path
or path segment. Finding the set of all such paths is somewhat easier because it is not necessary
to do all the intermediate products explicitly. The following algorithm is effective:
1. Express n – 2 as a binary number.
2. Take successive squares of (A + I), leading to (A + I)2 , (A + I) 4 , (A + 1)8 , and so on.
3. Keep only those binary powers of (A + 1) that correspond to a 1 value in the binary representation of
n – 2.
4. The set of all paths of length n – 1 or less is obtained as the product of the matrices you got in step 3
with the original matrix.
As an example, let the graph have 16 nodes. We want the set of all paths of length less than or
equal to 15. The binary representation of n – 2 (14) is 23 + 22 + 2. Consequently, the set of paths is given by

Ai=A(A+I)8(A+I)4(A+I)2
5.4. Loops
• Every loop forces us into a potentially infinite sum of matrix powers.
• Every loop shows up as a term in the diagonal of some power of the matrix—the power at
which the loop finally closes—or, equivalently, the length of the loop.
• The impact of the loop can be obtained by preceding every element in the row of the node at
which the loop occurs by the path expression of the loop term starred and then deleting the
loop term.

5.5. Partitioning Algorithm


Consider any graph over a transitive relation. The graph may
have loops. We would like to partition the graph by grouping nodes
in such a way that every loop is contained within one group or
another. Such a graph is partly ordered. There are many used for
an algorithm that does that:
1. We might want to embed the loops within a subroutine so as to
have a resulting graph which is loop free at the top level.
2. Many graphs with loops are easy to analyze if you know where
to break the loops.
3. While you and I can recognize loops,

Arbitrary graph
CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 25

The way to do this is straightforward. Calculate the following matrix: (A + I)n # (A + I)nT . This
groups the nodes into strongly connected sets of nodes such that the sets are partly ordered.
Furthermore, every such set is an equivalence class so that any one node in it represents the set.
Now consider all the places in this book where we said “except for graphs with loops” or “assume
a loop-free graph” or words to that effect. If you can bury the loop in a real subroutine, you can as
easily bury it in a conceptual subroutine. Do the analysis over the partly ordered graph obtained
by the partitioning algorithm and treat each loop-connected node set as if it is a subroutine to be
examined in detail later. For each such component, break the loop and repeat the process.
Here’s an example, worked with an arbitrary graph:
The relation matrix is

The transitive closure matrix is

Intersection with its transpose yields

CH.Johnwesily | [email protected]
Unit-5 Software Testing Methodologies 26

The algorithm leads to the following equivalent


node sets:
• A = [1]
• B = [2,7] whose graph is
• C = [3,4,5]
• D = [6]
• E = [8]
5.6. Breaking Loops And Applications
• Consider the matrix of a strongly connected sub
graph.
• If there are entries on the principal diagonal,
then start by breaking the loop for those links.
• Now consider successive powers of the matrix.
• At some power or another, a loop is manifested as an entry on the principal diagonal.
• The divide-and-conquer, or rather partition-and-conquer, properties of the equivalence
partitioning algorithm is a basis for implementing tools.
• The problem with most algorithms is that they are computationally intensive and require of
the order of n2 or n3 arithmetic operations, where n is the number of nodes.

CH.Johnwesily | [email protected]

You might also like