These techniques are useful during functional testing where the objective
is to test whether or not an application, unit, system, or subsystem,
correctly implements the functionality described in the requirements
Test summary
Test generation techniques report
© Aditya P. Mathur 2006
4
Functional Testing: Documents
Test Plan: Describe scope, approach, resources, test schedule,
items to be tested, deliverables, responsibilities, approvals needed.
Can be used at the system test level or at lower levels.
Test transmittal report: Identifies the test items being provided for
testing, e.g. a database.
8
Requirements and test generation
The problem of test selection is difficult due to the size and complexity
of the input domain of P.
© Aditya P. Mathur 2006
11
Exhaustive testing
The large size of the input domain prevents a tester from exhaustively
testing the program under test against all possible inputs.
The huge size of the input domain also makes it hard to select individual
tests.
15
Equivalence partitioning
Test selection using equivalence partitioning allows a tester to subdivide
the input domain into a relatively small number of sub-domains, say N>1.
The sub-domains by definition are disjoint. The four subsets shown in (a)
constitute a partition of the input domain while the subsets in (b) are not.
Each subset is known as an equivalence class.
This assumption allow the tester to select exactly one test from
each equivalence class resulting in a test suite of exactly N tests.
The entire set of inputs to any application can be divided into at least two
subsets: one containing all the expected, or legal, inputs (E) and the other
containing all unexpected, or illegal, inputs (U).
Each of the two subsets can be further subdivided into subsets on which the
application is required to behave differently (e.g. E1, E2, E3, and U1, U2).
All integers
Other integers
[1..120]
Further, assume that the application is required to process all values in the
range [1..61] in accordance with requirement R1 and those in the range
[62..120] according to requirement R2.
E is further subdivided into two regions depending on the expected behavior.
Similarly, it is expected that all invalid inputs less than or equal to 1 are to
be treated in one way while all greater than 120 are to be treated differently.
U is further subdivided two categories.
All integers
<1
[62-120] >120
[1..61]
© Aditya P. Mathur 2006
20
Example 1 (contd.)
Tests selected using the equivalence partitioning technique aim at targeting
faults in the application under test with respect to inputs in any of the four
regions, i.e. two regions containing expected inputs and two regions
containing the unexpected inputs.
It is expected that any single test selected from the range [1..61] will
reveal any fault with respect to R1.
Similarly, any test selected from the region [62..120] will reveal any fault
with respect to R2.
A similar expectation applies to the two regions containing the unexpected
inputs.
As is the case with any test selection technique in software testing, the
effectiveness of tests selected using equivalence partitioning is less than 1
for most practical applications.
begin
String w, f
Input w, f
if (not exists(f) {raise exception; return(0);}
if(length(w)==0) return(0);
if(empty(f)) return(0); Using the partitioning method described
in the examples above, we obtain the
return(getCount(w,f)); following equivalence classes.
end
© Aditya P. Mathur 2006
24
Example 2 (contd.)
Equivalence class w f
Based on the output equivalence classes one may now derive equivalence
classes for the inputs. Thus each of the four classes given above might
lead to one equivalence class consisting of inputs.
© Aditya P. Mathur 2006
27
Equivalence classes for variables:
range
struct transcript {
string fName; // First name.
string lName; // Last name.
string cTitle [200]; // Course titles.
char grades [200]; // Letter grades corresponding to course titles.
}
One way to partition the input domain is to consider one input variable
at a time.
1. Identify the input domain: Read the requirements carefully and identify
all input and output variables, their types, and any conditions associated
with their use.
Values for which the program is expected to behave in the “same way” are
grouped together (“same way” needs to be defined by the tester).
For example, suppose that an application is tested via its GUI, i.e., data is
input using commands available in the GUI. The GUI might disallow invalid
inputs by offering a palette of valid inputs only. There might also be
constraints in the requirements that render certain equivalence infeasible.
The command file may contain any one of the three commands, together
with the value of the temperature to be changed if the command is temp.
cmd
Control Software
GUI
tempch (CS)
These four values of tempch are tvalid, while all other values are tinvalid.
Recall that the domain identified in this step will likely be a superset of the
complete input domain of the control software.
F {{fvalid}, {finvalid}}
The GUI requests for the amount by which the boiler temperature is to be
changed only when the operator selects temp for cmd.
Thus, all equivalence classes that match the following template are infeasible.
In the most general case, a tester simply selects one test that
serves as a representative of each equivalence class.
54
Errors at the boundaries
Experience indicates that programmers make mistakes in processing values
at and near the boundaries of equivalence classes.
Certainly, tests derived using either of the two techniques may overlap.
3 Select test data such that each boundary value occurs in at least
one test input.
© Aditya P. Mathur 2006
57
BVA: Example: 1. Create
equivalence classes
Assuming that an item code must be in the range 99..999 and quantity in
the range 1..100,
0 2 99 101
* x * * x *
E4 1 100 E6
E5
Equivalence classes and boundaries for findPrice.
Boundaries are marked with an “x”, points near the boundary with a *.
© Aditya P. Mathur 2006
59
BVA: Example: 3. Construct test set
This may lead to boundaries that are not evident from equivalence
classes obtained from the input and output variables.
62
Where do predicates arise?
“if the printer is ON and has paper then send document to printer.”
We now examine two techniques, named BOR and BRO, for generating
tests guaranteed to detect certain faults in the coding of conditions.
The conditions from which tests are generated might arise from
requirements or might be embedded in the program to be tested.
< NOT
(a+b) c p
Leaf nodes
© Aditya P. Mathur 2006
70
Fault model for predicate testing
Ei has an off-by-ε fault if |e3-e4|= ε for any test case for which e1=e2.
Ei has an off-by-ε* fault if |e3-e4|>= ε for any test case for which e1=e2.
Ei has an off-by-ε+ fault if |e3-e4|> ε for any test case for which e1=e2.
Ei: a<b. Given c=1, Ei has an off-by-1 fault as |a-b|=1 for a test case
for which a=b+c, e.g., [a=2, b=1, c=1].
Ei: a<b-1. Given c>0, Ei has an off-by-1+ fault as |a-(b-1)|>1 for any
test case for which a=b+c, e.g., [a=3, b=2, c=1].
© Aditya P. Mathur 2006
75
Goal of predicate testing
Given a correct predicate pc , the goal of predicate testing is to generate a
test set T such that there is at least one test case t in T for which pc and its
faulty version pi evaluate to different truth values.
Such a test set guarantees the detection of any fault of the kind in the
fault model introduced above.
Correct predicate: a OR b
For example, consider the predicate E: a<b and the constraint “>”.
Consider predicate pr: b AND (r<s) OR (u ≥v) and constraint C : (t, =, >).
The following test case satisfies C for pr.
[b=true, r=1, s=1, u=1, v=0]
The following test case does not satisfy C for pr.
[b=true, r=1, s=2, u=1, v=2]
© Aditya P. Mathur 2006
81
Predicate testing: criteria
• T is minimal and
• T guarantees the detection of any fault in the implementation of pr
(faults correspond to the fault model we discussed earlier).
A BOR-adequate test set TBOR satisfying the BOR testing criterion for a
compound predicate pr guarantees the detection of single or
multiple Boolean operator faults in the implementation of pr .
A BRO-adequate test set TBRO satisfying the BRO testing criterion for a
compound predicate pr, guarantees the detection of single or multiple
Boolean operator and relational operator faults in the
implementation of pr .
A BRE-adequate test set TBRE satisfying the BRE testing criterion for a
compound predicate pr guarantees the detection of single or
multiple Boolean operator, relational expression, and
arithmetic expression faults in the implementation of pr .
© Aditya P. Mathur 2006
83
Predicate testing: guaranteeing fault
detection
Let Tx, x ∈ {BOR, BRO,BRE}, be a test set derived from predicate pr.
Let pf be another predicate obtained from pr by injecting single or multiple
faults of one of three kinds: Boolean operator fault, relational operator fault,
and arithmetic expression fault.
Tx detects faults in pf if, for some t ∈Tx , pr (t)≠ pf (t).
Example: let pr=a<b AND c >d. Constraint set S={(t, t), (t,f ), (f, t)}
TBOR={t1, t2, t3} is a BOR adequate test set that satisfies S.
t1: [a=1, b=2, c=1, d=0] Satisfies (t, t), i.e. a<b is true and c<d is true.
t2: [a=1, b=2, c=1, d=2] Satisfies (t, f )
t3: [a=1, b=0, c=1, d=0] Satisfies (f, t)
© Aditya P. Mathur 2006
84
Set products: Example
Recall that the cross product A×B of two sets A and B is defined as:
A×B={(u,v)|u ∈ A and v ∈ B }
A×B={(t, f), (t, <), (=, f), (=, <), (>,f), (>,<)}
A⊗B ={(t, f), (=,<), (>,<)} Any other possibilities for A⊗B?
Second, label each leaf node with the constraint set {(t),(f)}.
We label the nodes as N1, N2, and so on for convenience.
N1 and N2 are direct descendents of N3 which is an AND-node.
N3 AND
N1 a<b c >d N2
SN1= {(t),(f)} SN2= {(t),(f)}
Third, compute the constraint set for the next higher node in the syntax tree,
in this case N3. For an AND node, the formulae used are the following.
As per our objective, we have computed the BOR constraint set for the
root node of the AST(pr). We can now generate a test set using the
BOR constraint set associated with the root node.
p N2
© Aditya P. Mathur 2006
91
BRO constraint set: Example (contd.)
OR N6
N4
AND N5
r >s
N1 N3 {(>), (=), (<)}
a+b<c NOT
{(>), (=), (<)}
p N2
{(t), (f)}
© Aditya P. Mathur 2006
92
BRO constraint set: Example (contd.)
Step 2: Traverse the tree and compute constraint set for each internal node.
N6
OR
N4
AND N5
{(<,f),(>,f),(=,f),(<,t)}
r >s
{(>), (=), (<)}
N3 {(f), {t)}
N1 a+b<c NOT
{(>), (=), (<)}
p N2
{(t), (f)}
Next, compute the constraint set for the root node (an OR-node).
SfN6=SfN4 ⊗ SfN5
={(>,f), (=,f), (<,t)} ⊗ {(=), (<)}
={(>,f,=), (=,f,<), (<,t,=)}
N4 N5
{(<,f),(>,f),(=,f),(<,t)} AND
r >s
{(>),(=),(<)}
N1 N3 {(f), {t)}
a+b <c NOT
{(>),(=),(<)}
p N2
{(t),(f)}
© Aditya P. Mathur 2006
96
BRO constraint set: In-class exercise
Given the constraint set for pr : (a+b<c) AND NOT p OR (r >s), build TBRO.
{(>,f,=), (=,f,<),(<,t,=), (<,f,=),(>,f,>)}
Reading assignment:
Section 2.7.5.3, “Generating the BRE constraint set”, pages 165-167.
Step 1: Build a constraint set Te1 for e1 that makes e1 true and a
constraint set Te2 for e2 that makes e2 true.
The four t’s in the first element of Te1 denote the values of the boolean
variables a, b, c, and d, respectively. The second element, and others, are
to be interpreted similarly.
Step 2: From each Tei , remove the constraints that are in any other Tej.
This gives us TSei and Tsej , where TSei ∩TSej =∅.
There are no common constraints between Te1 and Te2 in our example.
Hence we get:
For each constraint x in StE we get E(x)=true. Also, StE is minimal. Check it out!
Note: Each constraint in StE makes E true and each constraint in SfE
makes E false.
We are now done with the MI procedure.
© Aditya P. Mathur 2006
106
BOR-MI-CSET procedure
We use the BOR-CSET procedure to generate the constraint set for e1 (singular
component) and MI-CSET procedure for e2 (non-singular component).
(Ste1 is the true constraint set for e1 and Sfe1 is the false constraint set for e1).
Summary:
N2
OR {(t,t,f), (f,t,t), (f,t,f), (t,f,t)}
AND AND
N1
a {(t),(f)}
b c !b d
Apply MI-CSET
© Aditya P. Mathur 2006
113
Summary
Equivalence partitioning and boundary value analysis are the most commonly
used methods for test generation while doing functional testing.