Module-2 TB
Module-2 TB
20
FUNCTIONAL TESTING
BOUNDARY VALUE TESTING, EQUIVALENCE CLASS TESTING,
DECISION TABLE-BASED TESTING
Any program can be considered to be a function in the sense that program inputs form
its domain and program outputs form its range. Input domain testing (also called
“boundary value testing”) is the best-known specification-based testing technique.
Historically, this form of testing has focused on the input domain; however, it is often a
good supplement to apply many of these techniques to develop range-based test cases.
There are two independent considerations that apply to input domain testing. The first
asks whether or not we are concerned with invalid values of variables. Normal
boundary value testing is concerned only with valid values of the input variables.
Robust boundary value testing considers invalid and valid variable values. The second
consideration is whether we make the “single fault” assumption common to reliability
theory. This assumes that faults are due to incorrect values of a single variable. If this
is not warranted, meaning that we are concerned with interaction among two or more
variables, we need to take the cross product of the individual variables. Taken
together, the two considerations yield four variations of boundary value testing:
21
Unfortunately, the intervals [a, b] and [c, d] are referred to as the ranges of x1 and x2,
so right away we have an overloaded term. The intended meaning will always be clear
from its context. Strongly typed languages (such as AdaR and Pascal) permit explicit
definition of such variable ranges. In fact, part of the historical reason for strong typing
was to prevent programmers from making the kinds of errors that result in faults that
are easily revealed by boundary value testing. Other languages (such as COBOL,
FORTRAN, and C) are not strongly typed, so boundary value testing is more
appropriate for programs coded in these languages. The input space (domain) of our
function F is shown in Figure above. Any point within the shaded rectangle and
including the boundaries is a legitimate input to the function F.
The next part of boundary value analysis is based on a critical assumption; it is known
as the “single fault” assumption in reliability theory. This says that failures are only
rarely the result of the simultaneous occurrence of two (or more) faults. The All Pairs
testing approach contradicts this, with the observation that, in software-controlled
medical systems, almost all faults are the result of interaction between a pair of
variables. Thus, the normal and robust variations cases are obtained by holding the
values of all but one variable at their nominal
22
1. So, these extreme ends like Start- End, Lower- Upper, Maximum-Minimum, Just
Inside-Just Outside values are called boundary values and the testing is called
"boundary testing".
2. The basic idea in boundary value testing is to select input variable values at their:
1. Minimum
2. Just above the minimum
3. A nominal value
4. Just below the maximum
5. Maximum
The basic idea of BVA is to use input variable values at their minimum, just above the
minimum, a nominal value, just below their maximum and at their maximum. Meaning
thereby (min, min+, nom, max-, max), as shown in the figure above.
BVA is based upon a critical assumption that is known as “Single fault assumption
theory”. According to this assumption, we derive the test cases on the basis of the fact
that failures are not due to simultaneous occurrence of two (or more) faults. So, we
derive test cases by holding the values of all but one variable at their nominal values
and allowing that variable assume its extreme values.
If we have a function of n-variables, we hold all but one at the nominal values and let
the remaining variable assume the min, min+, nom, max-and max values, repeating
this for each variable. Thus, for a function of n variables, BVA yields (4n + 1) test cases.
23
we can focus on exception handling. With strongly typed languages, robustness testing
may be very awkward. For example, in PASCAL, if a variable is defined to be within a
certain range, values outside that range result in run-time errors thereby aborting the
normal execution.
For a program with n-variables, robustness testing will yield (6n + 1) test-cases. Thus,
we can draw the following Robustness Test Cases graph. Each dot represents a test
value at which the program is to be tested. In Robustness testing, we cross the
legitimate boundaries of input domain. In the above graph, we show this by dots that
are outside the range [a, b] of variable x1. Similarly, for variable x2, we have crossed
its legitimate boundary of [c, d] of variable x2. This type of testing is quite common in
electric and electronic circuits. Furthermore, this type of testing also works on 'single
fault assumption theory'.
Worst-case test cases for a function of Robust worst-case test cases for a
two variables. function of two variables.
If we reject our basic assumption of single fault assumption theory and focus on what
happens when we reject this theory-it simply means that we want to see that what
happens when more than one variable has an extreme value. In electronic circuit
24
analysis, this is called as "worst-case analysis". We use this idea here to generate
worst- case test cases.
For each variable, we start with the five-element set that contains the min, min+, nom,
max-, and max values. We then take the Cartesian product of these sets to generate test
cases. This is shown in above graph. For a program with n-variables, 5n test cases are
generated.
25
7 1 2 2 isosceles
8 1 2 100 not a triangle
9 1 2 199 not a triangle
10 1 2 200 not a triangle
11 1 100 1 not a triangle
12 1 100 2 not a triangle
13 1 100 100 isosceles
14 1 100 199 not a triangle
15 1 100 200 not a triangle
16 1 199 1 not a triangle
17 1 199 2 not a triangle
18 1 199 100 not a triangle
19 1 199 199 isosceles
20 1 199 200 not a triangle
21 1 200 1 not a triangle
22 1 200 2 not a triangle
23 1 200 100 not a triangle
24 1 200 199 not a triangle
25 1 200 200 isosceles
26
14 15 1 2011 16 1 2011
15 15 1 2012 16 1 2012
16 30 1 1812 31 1 1812
17 30 1 1813 31 1 1813
18 30 1 1912 31 1 1912
19 30 1 2011 31 1 2011
20 30 1 2012 31 1 2012
21 31 1 1812 1 2 1812
22 31 1 1813 1 2 1813
23 31 1 1912 1 2 1912
24 31 1 2011 1 2 2011
25 31 1 2012 1 2 2012
27
6 10 10 9 975 97.5 Border point –
7 10 9 10 970 97 Border point –
8 9 10 10 955 95.5 Border point –
9 10 10 10 1000 100 Border point
10 10 10 11 1025 103.75 Border point +
11 10 11 10 1030 104.5 Border point +
12 11 10 10 1045 106.75 Border point +
13 14 14 14 1400 160 Midpoint
14 18 18 17 1775 216.25 Border point –
15 18 17 18 1770 215.5 Border point –
16 17 18 18 1755 213.25 Border point –
17 18 18 18 1800 220 Border point
18 18 18 19 1825 225 Border point +
19 18 19 18 1830 226 Border point +
20 19 18 18 1845 229 Border point +
21 48 48 48 4800 820 Midpoint
22 70 80 89 7775 1415 Output maximum –
23 70 79 90 7770 1414 Output maximum –
24 69 80 90 7755 1411 Output maximum –
25 70 80 90 7800 1420 Output maximum
The volume between the origin and the lower plane corresponds to sales below the $1000
threshold. The volume between the two planes is the 15% commission range. Part of
the reason for using the output range to determine test cases is that cases from the
input range are almost all in the 20% zone. We want to find input variable
combinations that stress the sales/commission boundary values: $100, $1000, $1800,
and $7800. The minimum and maximum were easy, and the numbers happen to work
out so that the border points are easy to generate.
Random Testing
At least two decades of discussion of random testing are included in the literature.
Most of this interest is among academics, and in a statistical sense, it is interesting. Our
three sample problems lend themselves nicely to random testing. The basic idea is
that, rather than always choose the min, min+, nom, max–, and max values of a
bounded variable, use a random number generator to pick test case values. This
avoids any form of bias in testing. It also raises a serious question: how many random
test cases are sufficient? Later, when we discuss structural test coverage metrics, we
will have an elegant answer.
28
Random Test Cases for Triangle Program
x = Int((b – a + 1) * Rnd + a)
where the function Int returns the integer part of a floating-point number, and the
function Rnd generates random numbers in the interval [0, 1]. The program keeps
generating random test cases until at least one of each output occurs. In each table, the
program went through seven “cycles” that ended with the “hard-to-generate” test case.
Guidelines for Boundary Value Testing
With the exception of special value testing, the test methods based on the input
domain of a function (program) are the most rudimentary of all specification-based
testing methods. They share the common assumption that the input variables are truly
independent; and when this assumption is not warranted, the methods generate
unsatisfactory test cases.
Another useful form of output-based test cases is for systems that generate error
messages. The tester should devise test cases to check that error messages are
generated when they are appropriate, and are not falsely generated.
Boundary value analysis can also be used for internal variables, such as loop control
variables, indices, and pointers. Strictly speaking, these are not input variables;
however, errors in the use of these variables are quite common. Robustness testing is
a good choice for testing internal variables.
29
Random Test Cases for NextDate Program
Equivalence Classes
The important aspect of equivalence classes is that they form a partition of a set,
where partition refers to a collection of mutually disjoint subsets, the union of which is
the entire set. This has two important implications for testing—the fact that the entire
set is represented provides a form of completeness, and the disjointedness ensures a
form of non-redundancy. The idea of equivalence class testing is to identify test cases
by using one element from each equivalence class. If the equivalence classes are
chosen wisely, this greatly reduces the potential redundancy among test cases.
The key of equivalence class testing is the choice of the equivalence relation that
determines the classes. The four forms of equivalence class testing all address the
30
problems of gaps and redundancies that are common to the four forms of boundary
value testing.
Weak Normal Equivalence Class Testing
3. Identify equivalence classes of valid values.
4. Test cases have all valid values.
5. Detects faults due to calculations with valid values of a single variable.
6. OK for regression testing.
7. Need an expanded set of valid classes
valid classes: {a <= x1 < b}, {b <= x1 < c}, {c <= x1 <= d}, {e <= x2 < f}, {f <= x2
<= g}
invalid classes: {x1 < a}, {x1 > d}, {x2 < e}, {x2 > g}
31
Strong Robust Equivalence Class Testing
17. Identify equivalence classes of valid and invalid values.
18. Test cases from Cartesian Product of all classes.
19. Detects faults due to interactions with any values of any number of variables.
20. OK for regression testing, better for progression testing.
(Most rigorous form of Equivalence Class testing, BUT,
Jorgensen’s First Law of Software Engineering applies.)
21. Jorgensen’s First Law of Software Engineering:
The product of two big numbers is a really big number.
(More elegant: scaling up can be problematic)
32
WN2 2 2 3 Isosceles
WN3 3 4 5 Scalene
WN4 4 1 2 Not a triangle
Here is one “corner” of the cube in three-space of the additional strong robust
equivalence class test cases:
Equivalence class testing is clearly sensitive to the equivalence relation used to define
classes.
33
Y1 = {year: 1812 ≤ year ≤ 2012} D2 = {day: day < 1}
D3 = {day: day > 31}
Y2 = {year: year < 1812}
Y3 = {year: year > 2012}
Because the number of valid classes equals the number of independent variables, only
one weak normal equivalence class test case occurs, and it is identical to the strong
normal equivalence class test case:
As with the triangle problem, here is one “corner” of the cube in three-space of the
additional strong robust equivalence class test cases:
Here is one “corner” of the cube in 3-space of the additional strong robust equivalence
class test cases:
35
Case ID Locks Stocks Barrels Expected Output
SR1 –2 40 45 Value of locks not in the range 1 ... 70
SR2 35 –1 45 Value of stocks not in the range 1 ... 80
SR3 35 40 –2 Value of barrels not in the range 1 ... 90
Value of locks not in the range 1 ... 70
SR4 –2 –1 45
Value of stocks not in the range 1 ...
80
Value of locks not in the range 1 ... 70
SR5 –2 40 –1
Value of barrels not in the range 1 ... 90
Value of stocks not in the range 1 ... 80
SR6 35 –1 –1
Value of barrels not in the range 1 ... 90
Value of locks not in the range 1 ... 70
SR7 –2 –1 –1 Value of stocks not in the range 1 ... 80
Value of barrels not in the range 1 ... 90
36
5. Equivalence class testing is strengthened by a hybrid approach with boundary value
testing. (We can “reuse” the effort made in defining the equivalence classes.)
6. Equivalence class testing is indicated when the program function is complex. In
such cases, the complexity of the function can help identify useful equivalence
classes, as in the NextDate function.
7. Strong equivalence class testing makes a presumption that the variables are
independent, and the corresponding multiplication of test cases raises issues of
redundancy. If any dependencies occur, they will often generate “error” test cases,
as they did in the NextDate function. (The decision table technique in Chapter 7
resolves this problem.)
8. Several tries may be needed before the “right” equivalence relation is discovered,
as we saw in the NextDate example. In other cases, there is an “obvious” or
“natural” equivalence relation. When in doubt, the best bet is to try to second-guess
aspects of any reasonable implementation. This is sometimes known as the
“competent programmer hypothesis.”
9. The difference between the strong and weak forms of equivalence class testing is
helpful in the distinction between progression and regression testing.
A decision table has four portions: the part to the left of the bold vertical line is the
stub portion; to the right is the entry portion. The part above the bold horizontal line is
the condition portion, and below is the action portion. Thus, we can refer to the
condition stub, the condition entries, the action stub, and the action entries. A column
in the entry portion is a rule. Rules indicate which actions, if any, are taken for the
circumstances indicated in the condition portion of the rule. In the decision table in
Table below, when conditions c1, c2, and c3 are all true, actions a1 and a2 occur. When
c1 and c2 are both true and c3 is false, then actions a1 and a3 occur. The entry for c3
in the rule where c1 is true and c2 is false is called a “don’t care” entry. The don’t care
entry has two major interpretations: the condition is irrelevant, or the condition does
not apply. Sometimes people will enter the “n/a” symbol for this latter interpretation.
When we use decision tables for test case identification, this completeness property of
a decision table guarantees a form of complete testing. Decision tables in which all the
conditions are binary are called Limited Entry Decision Tables (LETDs). If conditions
are allowed to have several values, the resulting tables are called Extended Entry
Decision Tables (EEDTs).
To identify test cases with decision tables, we interpret conditions as inputs and actions
as outputs. Sometimes conditions end up referring to equivalence classes of inputs, and
actions refer to major functional processing portions of the item tested. The rules are
then interpreted as test cases. Because the decision table can mechanically be forced to
be complete, we have some assurance that we will have a comprehensive set of test
cases. The don’t care entries (—) really mean “must be false.”
Use of don’t care entries has a subtle effect on the way in which complete decision
tables are recognized. For a limited entry decision table with n conditions, there must
be 2n independent rules. When don’t care entries really indicate that the condition is
irrelevant, we can develop a rule count as follows: rules in which no don’t care entries
occur count as one rule, and each don’t care entry in a rule doubles the count of that
rule.
Decision Table with Rule Counts
c1: a < b + c? F T T T T T T T T T T
38
c2: b < a + c? — F T T T T T T T T T
c3: c < a + b? — — F T T T T T T T T
c4: a = b? — — — T T T T F F F F
c5: a = c? — — — T T F F T T F F
c6: b = c? — — — T F T F T F T F
Rule Count 32 16 8 1 1 1 1 1 1 1 1
a1: Not a triangle X X X
a2: Scalene X
a3: Isosceles X X X
a4: Equilateral X
a5: Impossible X X X
Conditions R1 R2 R3
c1: Month in M1 T — —
c2: Month in M2 — T —
c3: Month in M3 — — T
Rule count 4 4 4
a1
Impossible Rules
Conditions 1.1 1.2 1.3 1.4 2.1 2.2 2.3 2.4 3.1 3.2 3.3 3.4
c1: Month in M1 T T T T T T F F T T F F
c2: Month in M2 T T F F T T T T T F T F
c3: Month in M3 T F T F T F T F T T T T
Rule count 1 1 1 1 1 1 1 1 1 1 1 1
a1: Impossible X X X — X X X — X X —
Conditions 1–4 5 6 7 8 9
c1 T F F F F T
c2 — T T F F F
c3 — T F T F F
39
a1 X X X — — X
a2 — X X X — —
a3 X — X X X X
Conditions 1–4 5 6 7 8 9
c1 T F F F F T
c2 — T T F F F
c3 — T F T F F
a1 X X X — — —
a2 — X X X — X
a3 X — X X X —
We obtain 11 functional test cases: three impossible cases, three ways to fail the triangle
property, one way to get an equilateral triangle, one way to get a scalene triangle, and
three ways to get an isosceles triangle
40
D4 = {day: day = 30}
D5 = {day: day = 31}
Y1 = {year: year is a leap year}
Y2 = {year: year is a common year}
Decision Table for NextDate Function
1 2 3 4 5 6 7 8 9 10
c1: Month in M1 M1 M1 M1 M1 M2 M2 M2 M2 M2
c2: Day in D1 D2 D3 D4 D5 D1 D2 D3 D4 D5
c3: Year in — — — — — — — — — —
Actions
a1: Impossible X
a2: Increment day X X X X X X X
a4: Reset day X X
a5: Increment month X X
a5: Reset month
a6: Increment year
11 12 13 14 15 16 17 18 19 20 21 22
c1: Month in M3 M3 M3 M3 M3 M4 M4 M4 M4 M4 M4 M4
c2: Day in D1 D2 D3 D4 D5 D1 D2 D2 D3 D3 D4 D5
c3: Year in — — — — — — Y1 Y2 Y1 Y2 — —
Actions
a1: Impossible X X X
a2: Increment day X X X X X X
a3: Reset day X X X
a4: Increment month X X
a5: Reset month X
a6: Increment year X
Cause-and-Effect Graphing
The most that can be learned from a cause-and-effect graph is that, if there is a
problem at an output, the path(s) back to the inputs that affected the output can be
retraced. There is little support for actually identifying test cases. Figure below shows
a cause- and-effect graph for the commission problem.
41
Cause-and-effect graph for commission problem
Guidelines and Observations
As with the other testing techniques, decision table–based testing works well for some
applications (such as NextDate) and is not worth the trouble for others (such as the
commission problem). Not surprisingly, the situations in which it works well are those
in which a lot of decision making takes place (such as the triangle problem), and those
in which important logical relationships exist among input variables (the NextDate
function).
1. The decision table technique is indicated for applications characterized by any of the
following:
a. Prominent if–then–else logic
b. Logical relationships among input variables
c. Calculations involving subsets of the input variables
d. Cause-and-effect relationships between inputs and outputs
e. High cyclomatic complexity
2. Decision tables do not scale up very well (a limited entry table with n conditions
has 2n rules). There are several ways to deal with this—use extended entry
decision tables, algebraically simplify tables, “factor” large tables into smaller ones,
and look for repeating patterns of condition entries. Try factoring the extended
entry table for NextDate.
3. As with other techniques, iteration helps. The first set of conditions and actions you
identify may be unsatisfactory. Use it as a stepping stone and gradually improve on
it until you are satisfied with a decision table.
42