SlideShare a Scribd company logo
1 of 142
$ÆD$Hè#A=A=’”ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è?=è?=
Ëè-èC=$‹Ì‰d$0RèùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËèÆD$pèF=ÇD-èC=$‹Ì‰d$0Rè
BW‹ÎètÆD$pèF=ÇD==ÿèƒÇÿÿÿÿ‹t$j‹Îèc<=PT$QD$ RPL$@èTþÿÿL$èÛ:=QRL$4è¸ýÿÿ
‹D$…À~AD$4L$PT$QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0R
èùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËè-C=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ
G=Æ
$hØ#PRŒ$€ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è
™êÿÿ‹N4jèßêËè-èC=$‹Ì‰d$0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-ÿÿPL$Æ
D$Hè#A=A=’”ÃèV@=”Ãè@=èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$
è“9=;Öt‹ASW‹°‹<
‰
‹A‰<°_[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê
Áé ó¥‹Èƒáó¤¾ìêøê

Æ„$¤ ’Æ„$¤Æ„èÛ:=$¤ÆD$pèF=ÇD‹Ì‰dÆD$pèF=ÇD$,PèŽ
G=ÆD$hØ#PèÛ:=RŒ$€
ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™ê[|,L$LT$PQ
h$èƒ?=è?=è?=-Ëè-èC=$‹ÌèÛ:=‰d$0RèùB>=$->=$L$(ÆD$DèÆèÛ:=D$pèF=ÇD¾==è°=
=‹|$PËè-èC=$‹Ëè-èC=$‹Ì‰d$0RèùBÿÿ‹N4jèßêÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=
-óÿÿPL$ÆD$Hè#A=A=’”ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è?
=è?=-Ëè-èC=$‹Ì‰d$0RèùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËèÆD$pèF=ÇD-èC=$‹Ì‰d$0
RèùBW‹ÎètÆD$pèF=ÇD==ÿèƒÇÿÿÿÿ‹t$j‹Îèc<=PT$QD$ RPL$@èTþÿÿL$èÛ:=QRL$4è¸ýÿ
ÿ‹D$…À~AD$4L$PT$QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0Rè
ùB>=$-=$L$(ÆD$Dè¾==è°==‹|$PËè-èC=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ
G=ÆD$hØ
#PRŒ$€ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™êÿÿ‹N
4jèßêËè-èC=$‹Ì‰d$0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-PL$ÆD$Hè#A=A=’”
ÃèV@=”Ãè@=èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$è“9=;Öt‹ASW‹°‹<

‰
‹A‰<°_[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê
Áé ó¥‹Èƒáó¤¾ìêøê
Æ„$¤ ’Æ„$¤Æ„èÛ
:=$¤ÆD$pèF=ÇD‹Ì‰dÆD$pèF=ÇD$,PèŽ
G=ÆD$hØ#PèÛ:=RŒ$€ÆD$t è4F=ÆD$pèF=
ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™ê[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$
‹ÌèÛ:=‰d$0RèùB>=$->=$L$(ÆD$DèÆèÛ:=D$pèF=ÇD¾==è°==‹|$PËè-èC=$‹Ëè-èC=$‹Ì‰
d$0RèùBÿÿ‹N4jèßêÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-óÿÿPL$ÆD$Hè#A=A=’”
ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0R
èùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËèÆD$pèF=ÇD-èC=$‹Ì‰d$0RèùBW‹ÎètÆD$pèF=
D==ÿèƒÇÿÿÿÿ‹t$j‹Îèc<=PT$QD$ RPL$@èTþÿÿL$èÛ:=QRL$4è¸ýÿÿ‹D$…À~AD$4L$PT$
QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0RèùB>=$->=$L$(ÆD$Dè
==è°==‹|$PËè-èC=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ
G=ÆD$hØ#PRŒ$€ÆD$t è4F=
ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™êÿÿ‹N4jèßêËè-èC=$‹Ì‰d$
0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-óÿÿPL$ÆD$Hè#A=A=’”ÃèV@=”Ãè@=
èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$è“9=;Öt‹ASW‹°‹<
‰
‹A‰<°
_[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê
Áé ó¥‹Èƒáó¤¾ìêøêÆ„$¤ ’Æ„$¤Æ„èÛ:=$¤ÆD$pèF=ÇD
$ÆD$Hè#A=A=’”ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è?=è?=
Ëè-èC=$‹Ì‰d$0RèùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËèÆD$pèF=ÇD-èC=$‹Ì‰d$0Rè
BW‹ÎètÆD$pèF=ÇD==ÿèƒÇÿÿÿÿ‹t$j‹Îèc<=PT$QD$ RPL$@èTþÿÿL$èÛ:=QRL$4è¸ýÿÿ
‹D$…À~AD$4L$PT$QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0R
èùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËè-C=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ
G=Æ
$hØ#PRŒ$€ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è
™êÿÿ‹N4jèßêËè-èC=$‹Ì‰d$0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-ÿÿPL$Æ
D$Hè#A=A=’”ÃèV@=”Ãè@=èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$
è“9=;Öt‹ASW‹°‹<
‰
‹A‰<°_[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê
Áé ó¥‹Èƒáó¤¾ìêøê

Æ„$¤ ’Æ„$¤Æ„èÛ:=$¤ÆD$pèF=ÇD‹Ì‰dÆD$pèF=ÇD$,PèŽ
G=ÆD$hØ#PèÛ:=RŒ$€
ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™ê[|,L$LT$PQ
h$èƒ?=è?=è?=-Ëè-èC=$‹ÌèÛ:=‰d$0RèùB>=$->=$L$(ÆD$DèÆèÛ:=D$pèF=ÇD¾==è°=
=‹|$PËè-èC=$‹Ëè-èC=$‹Ì‰d$0RèùBÿÿ‹N4jèßêÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=
-óÿÿPL$ÆD$Hè#A=A=’”ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è?
‹D$…À~AD$4L$PT$QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0Rè
ùB>=$-=$L$(ÆD$Dè¾==è°==‹|$PËè-èC=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ
G=ÆD$hØ
#PRŒ$€ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™êÿÿ‹N
4jèßêËè-èC=$‹Ì‰d$0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-PL$ÆD$Hè#A=A=’”
ÃèV@=”Ãè@=èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$è“9=;Öt‹ASW‹°‹<

‰
‹A‰<°_[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê
Áé ó¥‹Èƒáó¤¾ìêøê
Æ„$¤ ’Æ„$¤Æ„èÛ
:=$¤ÆD$pèF=ÇD‹Ì‰dÆD$pèF=ÇD$,PèŽ
G=ÆD$hØ#PèÛ:=RŒ$€ÆD$t è4F=ÆD$pèF=
Unit Testing
Software Quality Principles
Dr Danny Powell
K. J. Ross & Associates Pty. Ltd.
Suite 4, Ground Floor
13a Narrabang Way
Belrose NSW 2085
Telephone: 02 9450 2333
Facsimile: 02 9450 2744
Mobile: 0404 922 177
Email: dannyp@kjross.com.au
http//www.kjross.com.au
2
Test Driven Development
• http://www.testdriven.com/
“Test driven development (TDD) is emerging as one of the
most successful developer productivity enhancing
techniques to be recently discovered. The three-step: write
test, write code, refactor – is a dance many of us are
enjoying.”
3
Overview
 White-Box Test Design
 Unit Test Automation
 Unit/Integration Test Issues
4
Overview
 White-Box Test Design
– Statement, Branch and Path Coverage
– Loop Testing
– Decision Coverage
– Data Flow Coverage
 Unit Test Automation
 Unit/Integration Test Issues
5
White-Box Testing
• Common goal to exercise every path through a
program
– Infeasible to do this
• Techniques for selecting paths to test.
• Often associated with test coverage metrics
– Measure the percentage of paths of the selected type that
are exercised by test cases.
– Target coverage levels are set to guide how thoroughly a
program must be tested.
6
White-Box Testing
• White-box testing works at the code level
– The structure of the code is analysed to propose test cases
– Test paths are proposed based on the structure
7
Overview
 White-Box Test Design
– Statement, Branch and Path Coverage
– Loop Testing
– Decision Coverage
– Data Flow Coverage
– LCSAJ Coverage
– Pros and Cons
 Unit Test Automation
 Unit/Integration Test Issues
8
Statement, Branch and Path
Coverage
A
K
B
D E
H
C
F G
I
if A then
if B then
D
else
E
end if;
H
else
if C then
F
else
G
end if;
I
end if
9
Statement Coverage
• Each statement in the program visited by a test
– 10 statements
A
K
B
D E
H
C
F G
I










10
Branch Coverage
• Each branch in the logic visited by a test
– 6 branches
A
K
B
D E
H
C
F G
I
 




11
Path Coverage
• Each path through the logic visited by a test
– 4 paths
A
K
B
D E
H
C
F G
I
 


12
Test Case
• Execute test case and evaluate statements,
branches and paths visited
– test visits: A, B, D, H, K
– statement coverage
• 5/10 = 50%
– branch coverage
• 2/6 = 33%
– path coverage
• 1/4 = 25%
A
K
B
D E
H
C
F G
I
13
Statement, Branch and Path
Coverage Differences
Statement coverage without
branch coverage
Statement and branch
coverage without path
coverage
A
B
C
A
B C
D
E F
G
• 100% branch coverage gives 100% statement coverage
• 100% path coverage gives 100% branch coverage
14
Coverage Test Design
• Steps
– Analyse source code to derive flow graph
– Propose coverage test paths on flow graph
– Evaluate source code conditions to achieve each path
– Propose input and output values based on conditions
15
Binary Search
procedure Binary_Search (Key : ELEM; Table : ELEM_ARRAY;
Found : in out BOOLEAN; Row : in out ELEM_INDEX ) is
- - Assume that Table’FIRST and Table’LAST are both greater
- - than or equal to zero and Table’LAST >= Table’FIRST
Bot : ELEM_INDEX := Table’FIRST;
Top : ELEM_INDEX := Table’LAST;
Mid : ELEM_INDEX;
begin
Row := (Table’FIRST + Table’LAST) div 2;
Found := Table(Row) = Key;
while Bot <= Top and not Found loop
Mid := (Top + Bot) div 2;
if T( Mid ) = Key then
Found := true;
Row := Mid;
elsif T( Mid ) < Key then
Bot := Mid + 1;
else
Top := Mid – 1;
end if;
end loop;
end Binary_Search;
A
I
B
C
D
H
E
G
F
while Bot <= Top and not Found
if T(Mid) = Key then
if T(Mid) < Key then
J
16
Sample Run
Start
Loop 0
1 2 3 4 5 6 7 8 9 10
T =
Key = 6
1 2 3 4 5 6 7 8 9 10
T =
Bot Row Top
T(Row) = 5
Found = FALSE
Key = 6
17
Sample Run
Loop 1
1 2 3 4 5 6 7 8 9 10
T =
Bot
L,
Mid
Top
T(Mid) = 5
Found = FALSE
Key = 6
18
Sample Run
Loop 2
1 2 3 4 5 6 7 8 9 10
T =
Bot
Row Top
T(Mid) = 8
Found = FALSE
Key = 6
Mid
19
Sample Run
Loop 3
Exit Program (Found = TRUE; Row = 6)
1 2 3 4 5 6 7 8 9 10
T =
Bot,
Mid,
Row
Top
T(Mid) = 6
Found = TRUE
Key = 6
Row = 6
20
Propose Coverage Paths
• Come up with simple test cases that look at different
areas of coverage separately.
– For example, start with a simple single iteration of the loop -
1 search to the left (<)
 A, B, C, E, G, H, J, B, C, D, J, B, I
– This leaves only a path that visits node F to achieve 100%
path coverage
 A, B, C, E, F, H, J, B, C, D, J, B, I
• Use black-box techniques to propose initial cases and
review paths
21
Proposing Test Cases
• It is possible to work backwards from a path to obtain
a test case, but it takes some analysis
– May be necessary when your guesses at test cases still
aren’t covering the path you require
• You need to develop an understanding of the
conditions in the program that force a particular path
to be taken
– Must be able to trace the path through the program and
record the decisions that are made to stay on the path.
22
Propose Coverage Paths
• One path can provide
100% statement and
branch coverage (100%
path coverage is not
feasible):
A, B, C, E, F, H, J, B, C, E, G,
H, J, B, C, D, J, B, I
– This path corresponds to
the example illustrated
above.
A
I
B
C
D
H
E
G
F
while Bot <= Top and not Found
if T(Mid) = Key then
if T(Mid) < Key then
J
23
Propose Coverage Paths
• Some combinations of paths
in the graph will not be
achievable within the program
– E.g. the following gives 100%
statement and branch coverage
 A, B, C, D, J, B, C, E, F, H, J, B,
C, E, G, H, J, B, I
– This path is not possible
• B, C, D, J can’t happen first
A
I
B
C
D
H
E
G
F
while Bot <= Top and not Found
if T(Mid) = Key then
if T(Mid) < Key then
J
24
Review of Coverage Example
• Difficult to determine what paths are feasible and test
case values to satisfy paths
– Requires solid understanding of the program logic
– Easier to have a number of smaller paths
– Typical to first apply black-box testing, measure coverage,
and then use white-box testing to gain further coverage
• Sufficiency of test case questionable
– Didn’t consider both conditions on the while loop
• Possible to separate the conditions as two decisions in the flow
graph
– Didn’t cover loops in detail
25
Overview
 White-Box Test Design
– Statement, Branch and Path Coverage
– Loop Testing
– Decision Coverage
 Unit Test Automation
 Unit/Integration Test Issues
26
Loop Testing
• Loops easily lead to programs in which it is not
feasible to test all paths
– Combinatorial explosion
• Basis paths provide mechanism to tackle path
testing involving loops
• Zero-path
– Represents short circuit of the loop
• One-path
– Represent a loop in which only one iteration is performed
– Basis paths represents atomic components of all paths
• Possible paths are combinations and sequences of basis paths
27
Basis Path Testing
• Each basis path is exercised by at least one test
– Both for zero-path and one-path basis paths
• Combinations and sequences of basis paths do not
need to be exercised by a test
– They are covered by combinations and sequences of
already tested basis paths
28
Basis Path Example
• Binary_Search
– Basis Paths
• Zero-paths
– A, B, I
• One-paths
– B, C, D, J
– B, C, E, F, H, J
– B, C, E, G, H, J
A
I
B
C
D
H
E
G
F
while Bot <= Top and not Found
if T(Mid) = Key then
if T(Mid) < Key then
J
29
Review of Basis Path Testing
• Doesn’t consider
– Proper loop termination (e.g. reaching maximum value)
– Switching between conditions used in each iteration
30
Beizer’s Loop Tests [Bei95a]
• A number of other iteration test categories:
Bypass: any value that causes loop to be exited immediately
Once: values that cause the loop to be executed exactly once
Twice: values that cause the loop to be executed exactly twice
Typical: a typical number of iterations
Max: the maximum number of allowed iterations
Max + 1: one more than the maximum allowed
Max - 1: one less than the maximum allowed
Min: the minimum number iterations required
Min + 1: one more than the minimum required
Min - 1: one less than the minimum required
Null: one with a null or empty value for number of iterations
Negative: one with a negative value for number of iterations
• Some cases may overlap
– e.g. Bypass with Min/Null/Negative, etc.
31
Overview
 White-Box Test Design
– Statement, Branch and Path Coverage
– Loop Testing
– Decision Coverage
 Unit Test Automation
 Unit/Integration Test Issues
32
Branch Condition Testing
• Identifies individual boolean operands within
decisions
• Tests exercise individual and combinations of
boolean operand values
• Example:
if A or (B and C) then
do_something
else
do_something_else
33
Branch Condition Coverage
• Each operand is tested with values of TRUE and
FALSE
– Example’s operands
• A, B and C
– Weaknesses
• Can often be achieved with just two cases
• Can often be achieved without exercising both decision
outcomes
Case A B C
1 FALSE FALSE FALSE
2 TRUE TRUE TRUE
Case A B C
1 TRUE FALSE FALSE
2 FALSE TRUE TRUE
34
Branch Condition
Combination Coverage
• All combination of boolean operand values
Case A B C
1 FALSE FALSE FALSE
2 TRUE FALSE FALSE
3 FALSE TRUE FALSE
4 TRUE TRUE FALSE
5 FALSE FALSE TRUE
6 TRUE FALSE TRUE
7 FALSE TRUE TRUE
8 TRUE TRUE TRUE
• Requires 2n cases
for n operands for
100% coverage
• Rapidly becomes
infeasible for more
complex conditions
35
Modified Condition Decision
Coverage
• Pragmatic compromise that requires fewer test cases
than branch condition combination
– Used widely in avionics software
• Required by RTCA/DO-178B
• Show that each boolean operand can independently
affect the decision outcome
36
Modified Condition Decision
Coverage
• Decision outcome = A or (B and C)
Case A B C Outcome
A1 FALSE FALSE TRUE FALSE
A2 TRUE FALSE TRUE TRUE
Case A B C Outcome
B1 FALSE FALSE TRUE FALSE
B2 FALSE TRUE TRUE TRUE
Case A B C Outcome
C1 FALSE TRUE FALSE FALSE
C2 FALSE TRUE TRUE TRUE
37
Modified Condition Decision
Coverage
• Minimal tests: A1 & B1 same, B2 & C1 same
• 100% coverage requires
– minimum of n+1 test cases
– maximum of 2n test cases
Case A B C Outcome
1 (A1, B1) FALSE FALSE TRUE FALSE
2 (A2) TRUE FALSE TRUE TRUE
3(B2, C2) FALSE TRUE TRUE TRUE
4 (C1) FALSE TRUE FALSE FALSE
38
Condition Coverage Issues
• Placement of boolean conditions outside decision
FLAG := A or (B and C)
if FLAG then …
– Variation is to test for all boolean expressions
• Compiler optimisation
– C and C++ short-circuits && and ||
– Not possible to show coverage
• Other decision structures
– Case and switch statements
39
White-Box Techniques
Conclusions
• Useful for analysing particular paths in programs to
exercise them with tests
• Gives rise to large number of test cases
• Used in conjunction with black-box techniques
– Look for unexecuted parts of program
• Techniques are also useful when applied as black-
box techniques
– Specification involving logic are used in place of source code
(e.g. flow chart; transaction scenario diagram)
40
Pros and Cons of White-Box
Testing
Advantages
– Easier to identify decisions, and equivalence classes that
are being used in the logic than with black-box testing
– More objective than black box testing, different people
deriving test cases will arrive at corresponding results
– Automated tools available to propose paths to test and to
monitor coverage as the code is tested
41
Pros and Cons of White-Box
Testing
Disadvantages
- Incorrect code gives rise to tests that do not conform to
expected operation as well
- Can’t detect wrong function being implemented, or missing
functions or code.
- Need to have a good understanding of the code to
understand the meaning of each test path through the code
- Some paths are difficult to visit
- Doesn’t consider interfacing issues
- Need access to the code
42
Pros and Cons of White-Box
Testing
More disadvantages
- Impossible to test “spaghetti code” or “pacincko code” as
there are excessive numbers of paths
- Problems with multiple processes, threads, interrupts, event
processing
- Dynamically changing data and code is difficult to analyse
- Only practical at low levels, for whole systems the number of
paths through a whole program is incredibly large
43
• How could white-box techniques be applied to your
black-box testing approaches?
Discussion
44
Overview
 White-Box Test Design
 Unit Test Automation
– Unit Test Frameworks
– Unit Test Tools
 Unit/Integration Test Issues
45
Overview
 White-Box Test Design
 Unit Test Automation
– Unit Test Frameworks
– Unit Test Tools
 Unit/Integration Test Issues
46
Unit Test Frameworks
• Provides the test scaffolding around the code under
development
• Available tools:
– Commercial Tools
• Jtest, Cantata, etc.
– Extreme Programming frameworks (OpenSource)
(http://c2.com/cgi/wiki?TestingFramework)
• Junit, HTTPUnit, DelphiUnit, CppUnit, PerlUnit, PhPUnit, etc.
47
JUnit
• Java (code-level) regression testing framework
– Written by Erich Gamma & Kent Beck
• See www.junit.org
• Open Source
• Many extensions and documentation
48
Building JUnit Tests
1. Define a subclass of TestCase
2. Override the setUp() method to initialise objects
under test
3. Override the tearDown() method to release objects
under test
4. Define one or more testXXX() methods to exercise
objects under test
5. Define a suite() factory method the creates all the
testXXX() methods or the TestCase
6. Define a main() method to run the TestCase
49
Case Study - Money Class
class Money {
private int fAmount;
private String fCurrency;
public Money(int amount, String currency)
{ fAmount= amount;
fCurrency= currency;
}
public int amount() {
return fAmount;
}
public String currency() {
return fCurrency;
}
public Money add(Money m) {
return new Money(amount()+m.amount(), currency());
}
}
50
Case Study - Test Case
public class MoneyTest extends TestCase {
//…
public void testSimpleAdd() {
Money m12CHF= new Money(12, CHF");
Money m14CHF= new Money(14, "CHF");
Money expected= new Money(26, "CHF");
Money result=m12CHF.add(m14CHF);
assert(expected.equals(result));
}
}
Object Creation
Method Under Test
Result Verification
assert - check boolean result is true
Junit Test Case
• Need an equals method in Money
51
Case Study - Test Case
• Create test for Equals first
public void testEquals() {
Money m12CHF= new Money(12, "CHF");
Money m14CHF= new Money(14, "CHF");
assert(!m12CHF.equals(null));
assertEquals(m12CHF, m12CHF);
assertEquals(m12CHF, new Money(12, "CHF"));
assert(!m12CHF.equals(m14CHF));
}
Result Verification
assertEquals - compare two values
52
Case Study - Optimised Test
Cases
public class MoneyTest extends TestCase {
private Money f12CHF;
private Money f14CHF;
protected void setUp() {
f12CHF= new Money(12, "CHF");
f14CHF= new Money(14, "CHF"); }
public void testEquals() {
assert(!f12CHF.equals(null));
assertEquals(f12CHF, f12CHF);
assertEquals(f12CHF, new Money(12, "CHF"));
assert(!f12CHF.equals(f14CHF)); }
public void testSimpleAdd() {
Money expected= new Money(26, "CHF");
Money result= f12CHF.add(f14CHF);
assert(expected.equals(result)); }
}
• setUp & tearDown
methods available
to manage objects
53
Case Study - Test Suite
public static Test suite() {
TestSuite suite= new TestSuite();
suite.addTest(new MoneyTest("testEquals"));
suite.addTest(new MoneyTest("testSimpleAdd"));
return suite; }
• Suite is a static method
• Test cases are added to the suite
54
Case Study - Running Tests
/**
* Uncomment choice of UI
**/
public static void main() {
String[] testCaseName = {MoneyTest.class.getName()};
// junit.textui.TestRunner.main(testCaseName);
// junit.swingui.TestRunner.main(testCaseName);
junit.ui.TestRunner.main(testCaseName);
}
• Choice of:
• Textual UI
• Swing UI
• AWT UI
55
JUnit
• Reports failures - expected and actual
• Summarises outcomes
56
• JUnit
• Ant
• JCoverage
• Cruise Control
Demonstration
57
Ant
• http://jakarta.apache.org/ant/index.html
• Similar to make
• Cross-platform
• Defacto standard for Java builds
• Support for continuous integration:
– Build
– Test
– Documentation
– Package
– Deploy
• NAnt – similar framework on .Net
58
Code Coverage
• Shows code
visited after
completing tests
• Screen shot of
Jcoverage (GPL)
• www.jcoverage.com
59
Code Coverage
• Drill down to view
the Class code
• Graphically shows
the code missed in
the listing
60
Cruise Control
http://cruisecontrol.sourceforge.net/
• CruiseControl is a framework for a continuous build
process
• It includes
– plugins for email notification
– Ant
– various source control tools
– Web interface is provided to view the details of the current
and previous builds
• Also CruiseControl.NET
61
eLVAS Cruise Control
62
eLVAS Cruise Control
63
eLVAS Cruise Control
64
Unit Test Organisation
• Create the tests in the same package as the code
under test
• For each Java package in the application, define a
TestSuite class that contains all the tests for verifying
the class
• Make sure the build process includes the compilation
of all test suites and test cases
65
Unit Test Principles
• Code a little, test a little, code a little, test a little
• Run tests as often as possible, at least as often as you run compiler
• Run all the tests in the system at least once per day
• Begin by writing tests for the area of code that your most worried
about breaking
• Write tests that have highest possible return on your testing
investment
• When you need to add new functionality, add the tests first
• If you find yourself debugging using println, write a test case instead
• When a bug is reported, write a test case to expose the bug
• Next time someone asks for help debugging, write a test case to
expose the bug
• Don’t deliver code that doesn’t pass all the tests
66
Other Frameworks
http://c2.com/cgi/wiki?TestingFramework
• AsUnit - Action Script
• ASPUnit - ASP using VB
• CPPUnit - C++, C#
• CuUnit - VisualC++
• COMUnit
• DelphiUnit
• DotNetUnit, DotUnit - .net
• EiffelUnit
• ForteUnit
• JsUnit - Javascript
• LingoUnit
• Nunit, NUnitASP,
NUnitForms
• PerlUnit
• PhPUnit
• PLSQLUnit - Oracle
• PowerBuilderUnit
• PythonUnit
• SmallTalkUnit
• VBUnit
• VBAUnit
• XMLUnit
• XSLTUnit
67
HTTP Unit
• Free, Opensource JAVA API
• Accesses web sites without browser
• Combined with Junit
• framework for web testing
• Designed and implemented by Russell Gold
68
HTTP Unit
WebConversation wc = new WebConversation();
WebRequest req = new GetMethodWebRequest("http://www.meterware.com/testpage.html"
);
WebResponse resp = wc.getResponse( req );
• WebConversation class
• Takes the place of a browser talking to a single site
• Maintains session context, which it does via cookies
returned by the server
• Response manipulated either as pure text (via the
toString() method), as a DOM (via the getDOM() method),
or by using the various other methods
WebConversation wc = new WebConversation();
WebResponse resp = wc.getResponse( "http://www.meterware.com/testpage.html" );
69
HTTP Unit
WebConversation wc = new WebConversation();
// read page
WebResponse resp = wc.getResponse( "http://httpunit.sourceforge.net/doc/Cookbook.html"
);
// find the link
WebLink link = resp.getLinkWith( "response" );
// convert it to a request
WebRequest req = link.getRequest();
// retrieve the referenced page
WebResponse jdoc = wc.getResponse( req );
• Navigation
• Retrieve and follow links
• Image links can be followed
• WebResponse.getLinkWithImageText()
70
HTTP Unit
// select the first form in the page
WebForm form = resp.getForms()[0];
assertEquals( "La Cerentolla", form.getParameterValue( "Name" ) );
assertEquals( "Chinese", form.getParameterValue( "Food" ) );
assertEquals( "Manayunk", form.getParameterValue( "Location" ) );
assertEquals( "on", form.getParameterValue( "CreditCard" ) );
• Form evaluation
• Properties
• Submit request = form.getRequest();
request.setParameter( "Food", "Italian" );
request.removeParameter( "CreditCard" );
response = wc.getResponse( request );
71
HTTP Unit
WebTable table = resp.getTables()[0];
assertEquals( "rows", 4, table.getRowCount() );
assertEquals( "columns", 3, table.getColumnCount() );
assertEquals( "links", 1, table.getTableCell( 0, 2 ).getLinks().length );
• Table evaluation
• Properties
• Content String[][] colors = resp.getTables()[1].asText();
assertEquals( "Name", colors[0][0] );
assertEquals( "Color", colors[0][1] );
assertEquals( "gules", colors[1][0] );
assertEquals( "red", colors[1][1] );
assertEquals( "sable", colors[2][0] );
assertEquals( "black", colors[2][1] );
name color
gules red
sable black
72
HTML Unit
• Like HTTP Unit
• Extensions for supporting Javascript (latest version)
– Uses Apache Rhino javascript interpreter
73
SQLUnit
http://sqlunit.sourceforge.net
• Regression and unit testing harness for testing
database stored procedures.
• Test suite written as an XML file.
• The SQLUnit harness is written in Java
– Uses the JUnit unit testing framework to convert the XML
test specifications to JDBC calls and compare the results
generated from the calls with the specified results.
– It should be possible, at least in theory, to write unit tests for
stored procedures for any database that provides a JDBC
driver.
74
SQLUnit
GUI Tool
• Generates test
<test name="Checking returned value from customer">
<sql>
<stmt>select custId from customer where custId=?</stmt>
<param id="1" type="INTEGER" inout="in" is-null="false">
1</param>
</sql>
<result><resultset id="1">
<row id="1"><col id="1" type="INTEGER">1</col></row>
</resultset></result>
</test>
75
SQLUnit Output
Buildfile: build.xml init: test-ant-task:
[sqlunit] Getting connection...
[sqlunit] Setting up test...
[sqlunit] Running test[1]: Adding department HR
[sqlunit] Running test[2]: Adding department InfoTech using non-Callable form
[sqlunit] Running test[3]: Adding Employee John Doe to InfoTech
[sqlunit] Running test[4]: Adding John Doe again
[sqlunit] Running test[5]: Adding Jane Doe to HR
[sqlunit] Running test[6]: Adding Dick Tracy to InfoTech
[sqlunit] Running test[7]: Updating Hourly Rate for John
[sqlunit] Running test[8]: Looking up John Doe by name
[sqlunit] Running test[9]: Looking up all employees in InfoTech
[sqlunit] Running test[10]: Adding timecard for John
[sqlunit] Running test[11]: Adding another timecard for John
[sqlunit] Running test[12]: Adding timecard for Dick
76
[sqlunit] Running test[13]: Getting monthly report for InfoTech
[sqlunit] No match on variable at [rset,row,col]=([1,1,4]
[sqlunit] *** expected:
[sqlunit] <result>
[sqlunit] <resultset id="1">
[sqlunit] <row id="1">
[sqlunit] <col id="1" type="VARCHAR">Information Technology</col>
[sqlunit] <col id="2" type="VARCHAR">John Doe</col>
[sqlunit] <col id="3" type="INTEGER">16</col>
[sqlunit] <col id="4" type="NUMERIC">56.00</col>
[sqlunit] <col id="5" type="NUMERIC">880.00</col>
[sqlunit] </row>
[sqlunit] <row id="2">
[sqlunit] </row>
sqlunit] </resultset>
[sqlunit] </result>
[sqlunit] *** but got:
[sqlunit] <result>
[sqlunit] <resultset id="1">
[sqlunit] <row id="1">
[sqlunit] <col id="1" type="VARCHAR">Information Technology</col>
[sqlunit] <col id="2" type="VARCHAR">John Doe</col>
[sqlunit] <col id="3" type="INTEGER">16</col>
[sqlunit] <col id="4" type="NUMERIC">55.00</col>
[sqlunit] <col id="5" type="NUMERIC">880.00</col>
[sqlunit] </row>
[sqlunit] </resultset>
[sqlunit] </result>
[sqlunit] Tearing down test...
[sqlunit] Time: 1.204
[sqlunit] OK (1 tests)
[sqlunit] BUILD SUCCESSFUL Total time: 2 seconds
77
DBUnit
http://dbunit.sourceforge.net
• JUnit extension that puts your database into a known
state between test runs
– Helps you avoid the problems that can occur when one test
corrupts the database and causes subsequent tests to fail or
give faulty results.
– It can read the contents of a table and store it to XML using
a FlatXmlDataSet
78
DBUnit
• Table data saved as XML for restore during testing
<EMPLOYEE
employee_uid='1‘
start_date='2001-01-01‘
first_name='Andrew‘
ssn=‘000-29-2030‘
last_name='Glover‘
/>
79
Nunit
• .Net framework
• Similar to JUnit
80
Nunit Example
StackTest.cs
• See Book Chapter
http://richclients.org/files/newkirk/TDD%20in%20Microsoft%20.NET%20Chapter%202.pdf
using System;
using NUnit.Framework;
[TestFixture]
public class StackFixture
{
private Stack stack;
[SetUp]
public void Init()
{
stack = new Stack();
}
[Test]
public void Empty()
{
Assert.IsTrue(stack.IsEmpty);
}
[Test]
public void PushOne()
{
stack.Push(“first element”);
Assert.IsFalse(stack.IsEmpty,
“After Push, IsEmpty should
be false”);
}
[Test]
public void Pop()
{
stack.Push(“first element”);
stack.Pop();
Assert.IsTrue(stack.IsEmpty,
“After Push - Pop, IsEmpty
should be true”);
}
…
…
81
Nunit Example
Stack.cs
using System;
using System.Collections;
public class Stack
{
private ArrayList elements = new
ArrayList();
public bool IsEmpty
{
get
{
return (elements.Count ==
0);
}
}
public void Push(object element)
{
elements.Insert(0, element);
}
public object Pop()
{
object top = Top();
elements.RemoveAt(0);
return top;
}
public object Top()
{
if(IsEmpty)
throw new
InvalidOperationException(
“Stack is Empty”);
return elements[0];
}
}
82
• What are the perceived pros and cons of test driven
development, continuous integration, and iterative
releases
• Develop a checklist of recommendations
– areas to encourage
– areas to avoid
Discussion
83
• Review other Junit tools on
www.junit.org
Discussion
84
Overview
 White-Box Test Design
 Unit Test Automation
– Unit Test Frameworks
– Unit Test Tools
 Unit/Integration Test Issues
85
Tools to Aid in Testing
• Debugger
– e.g. softice
• test coverage
– e.g TCMON, PureCoverage, Numega, ATTOL, C-Cover, CTC++,
TCAT
• memory analysis (usage, leaks, etc)
– e.g. BoundsChecker, Purify, GlowCode,
• Performance
– e.g. Quantify, Jprobe
• Integrated
– Cantata, AdaTest, JTest, VectorCAST
See Source Tools at http://www.aptest.com/resources.html
86
Testing with a Debugger
• In general, a slow, labour-intensive way to test
• Should not be used to test new developments
– A proper test suite may take longer to create but when
regression test runs are required (and they will be) you will
save more time in the long run
• Can be useful as a last resort when maintaining badly
designed software with no test suite
87
Testing with a Debugger
Procedure
– Start the program and breakpoint the method requiring test
– Exercise a program feature that will trigger a call to the
method
– Change the input parameters and object state in the
debugger as appropriate to set up the test pre-state
– Either step through the code or breakpoint the end of the
method and examine the post-state against expected
criterion
– You should document the tests done so that they can be
repeated if necessary (as a checklist)
88
Types of Test Coverage
• Types of test coverage, in order of difficulty and
completeness
– Statement (or segment) coverage
– Branch Coverage
– Branch Condition Coverage
– Multiple-Condition Coverage
– Path Coverage
– Exhaustive coverage (rarely possible)
89
Test Coverage
How much coverage is enough?
• “It compiled!”
• “I ran through it a couple of times and it
seemed to work okay.”
• “I ran 64 test cases and achieved 100%
statement and 77% branch coverage.”
90
Test Coverage
• IEEE 1008 requires a minimum 100%
statement coverage (as does IBM’s corporate
standard)
– statement coverage alone is not considered a
good criterion of test coverage
• A high branch coverage in addition to
statement coverage is a better indication of
good test coverage (but may be difficult to
achieve)
91
Test Coverage - Case Study
Percent Coverage
System
Under Test
Segment Branch
TeX 85 72
AWK 70 59
• Test coverage achieved by functional test suites for
AWK and TeX
Source: Handbook of software reliability engineering, Horgan, 1996
92
Getting High Test Coverage
• High test coverage is difficult when code depends on
the results of external modules.
– replace external modules with stubs
– stubs are designed to return values which will exercise
different paths of the code
– Discussion: what approaches could be used to test the error
handling in the following fragment of C?
mem = (char *) malloc(MEMSIZE);
if (mem != null) {
/* do something with mem */
}
else {
/* error handling */
}
93
Test Coverage - a Final Note
• Sometimes it seems that getting 100% statement
coverage is impossible. There may be good reasons:
– tests are run with debugging code compiled into the
executable, but the debugging code is switched off (i.e
protected by conditionals)
– some of the code is dead and can never be executed.
• When maintenance is done on a program and old code is left
hanging around because “somebody might need it”, this is
known as “Lava Flow”.
• With proper Configuration Management, there is no excuse for
leaving dead code around; test coverage analysis can help to
find dead code.
94
Code Coverage Tools
• Instrument the code during compile
• When the code is run it collects coverage data
• Assess coverage to determine where to extend tests
• See http://c2.com/cgi/wiki?CodeCoverageTools
95
http://c2.com/cgi/wiki?CodeC
overageTools
for Java
• EMMA @ http://emma.sourceforge.net/
• Hansel @ http://hansel.sourceforge.net/
• jcoverage @ http://www.jcoverage.com/
• Clover @ http://www.thecortex.net/clover/
• GroboUtils @ http://groboutils.sourceforge.net
• NoUnit? @ http://nounit.sourceforge.net/
• Quilt @ http://quilt.sourceforge.net/
• Gretel @ http://sourceforge.net/projects/gretel
• The "Java Test Coverage Tool" @
http://www.semanticdesigns.com/Products/TestC
overage/JavaTestCoverage.html
• MutationTesting: (which isn't really
CodeCoverage, but it's related)
• JesTer @ http://jester.sourceforge.net/
for .NET:
• NCover @ http://ncover.sourceforge.net/
• CoverageEye?.NET @
http://www.gotdotnet.com/Community/UserSamples/Deta
ils.aspx?SampleGuid=881a36c6-6f45-4485-a94e-
060130687151
• The "C# Test Coverage Tool" @
http://www.semanticdesigns.com/Products/TestCoverage
/CSharpTestCoverage.html
• "DevPartner? Studio Professional Edition" @
http://www.compuware.com/products/devpartner/1563_E
NG_HTML.htm
• "Perform Code Coverage Analysis with .NET to Ensure
Thorough Application Testing", an MSDN article on
building "A custom code coverage tool" @
http://msdn.microsoft.com/msdnmag/issues/04/04/CodeC
overageAnalysis/default.aspx
C/C++:
• tcov = Sun Unix C profiler. See "tcov(1)" man page. It
annotates (mangles) your source code to add
instrumentation.
• gcov = GNU C/C++ equivilent of "tcov".
• Dynamic Code Coverage for Sun Solaris @
http://www.dynamic-memory.com/coverageanalysis.php
96
Test Coverage
• Compilation setup
• Logging tests
• Results
97
Test Coverage
98
Test Coverage Tools
Tool Statement Branch Multiple-
Condition
Decision
Path
Rational
Pure
Coverage
   
TestWell
CTC++    
McCabe
Tools    
99
Memory Bugs
• Common memory use bugs
– memory allocated in constructors is not de-allocated in
corresponding destructors (or anywhere else)
– indexed memory reads and writes go out of bounds
– memory is not initialised before use
– memory is not accessed after de-allocation
• Rational Purify detects all of these things (plus others)
• GPL or free libraries exist that detect these bugs by
replacing memory management routines
– search for “memory leak” on www.freshmeat.net
– are usually specific to UNIX/Linux and GCC
100
Memory Leak Detection
• Instrument the code during compile
• When the code is run it collects memory allocation
data
• When the code closes it looks for leaked memory
101
Memory Leak Detection
• Compile
• Run
• Find error
102
Purify
• Leak detection finds memory leaks which consume more
memory
103
Performance Bugs
• Module testing should aim to identify and eliminate
bottlenecks
– without a performance analysis tool, optimisation efforts are
nearly always wasted efforts
• The following tools can highlight performance
problems:
– gprof (free on Linux)
– Rational Quantify for UNIX and NT
104
Performance Measurement
• A performance analysis tool may have some or all of
the following features:
– time spent in a function or method
– time spent in a program segment
– contributing time of called functions
• Times may be specified as % of total, clock cycles or
wall time
105
Quest JProbe
• Analyse call hierarchy of Java applications
106
Overview
 White-Box Test Design
 Unit Test Automation
 Unit/Integration Test Issues
– Harnesses & Stubs
107
Overview
 White-Box Test Design
 Unit Test Automation
 Unit/Integration Test Issues
– Module / Unit Testing
– Integration Levels
– Integration Testing
– Harnesses & Stubs
– Test Oracles
– Object-Orientation Concerns
– Coding Standards
108
Module (Unit) Testing
• Module Testing is applied at the level of each module
of the system under test.
• Module testing is nearly always done by the
developers themselves, before the module is handed
over for integration with other modules.
• Usually the testing at this level is structural (white-
box) testing.
• Module Testing is sometimes called Unit Testing
representing the lowest level item available for
testing.
109
Module Testing Questions
• Has the component interface been fully tested?
• Have local data structured been exercised at their
boundaries?
• Have all independent basis paths been tested?
• Have all loops been tested appropriately?
• Have data flow paths been tested?
• Have all error handling paths been tested?
110
White Box Module Testing
The goal is to extensively test the code
with a view to exposing and fixing bugs
prior to integration with other’s work.
• Finds lurking bugs that are very hard to find cost-
effectively during integration or functional testing
• Tools are essential to get test coverage data
• REMEMBER: Caution is required
– you must have a specification against which to test
– without a spec, you are simply testing that the code does
what you think it does (but is it doing the RIGHT thing?)
111
Module Test Technique
• The module under test is usually treated as a white
box; however a “grey” box is more appropriate:
1. Systematic test design techniques are applied to the
specification of the module
2. The module is tested
3. If any tests fail the module is debugged and the process is
repeated from step 2
4. Test coverage is evaluated: if coverage criteria is met then
the module is considered verified; otherwise the process is
repeated from step 1
• knowledge of the algorithms in use can help find new
test cases when coverage is too low
112
Module Test Approaches
• Ad-hoc
• Checklist
• Automated
• Planned
113
Adhoc Approach
Usually the task of the implementing developer
• Ad-hoc approach: random testing before the modules
are handed over for integration
Pros
– quick (sometimes very quick)
Cons
– Difficult to quantify how well the code was tested before
integration
– Bugs slip through to later testing where they are much more
difficult (and costly) to find and fix
– Less likely that the developer will design testable code
114
Checklist Approach
A module test checklist is the set of abbreviated test
cases used by a developer to ensure thorough testing
of their module.
– Called a checklist because it usually lists inputs and
expected results and has a checkbox to indicate the result of
executing the test
– may not be applicable if tests are automated; although the
automated test may have its origins in a test checklist
115
Checklist Approach
Checklists are more suitable for developer testing than
standard test plans because:
– they minimise the amount of work required of a developer to
prepare a repeatable set of test cases
– a developer does not require detailed test instructions
because they already know how to apply a test to their own
code
– YOU try getting a developer to write an IEEE 829 compliant
test plan!
116
Example Test Checklists
Module Specific
class IntSet {
...
void add(int i); // contains(i) => exception; otherwise adds i
void remove(int i); // !contains(i) => exception; otherwise removes i
bool contains(int i); // returns true iff i is contained in the set
...
}
ID Test Case Check
S1 contains(x) fails for all values of x when empty set is constructed
S2 add value 1 to empty set succeeds
S3 add value 1 to set containing 1 (post S2) throws exception
etc…
117
Example Test Checklists
Generic 1
Myers 1979
1. Is the number of input parameters equal to number of arguments?
2. Do parameter and argument attributes match?
3. Do parameter and argument units system match?
4. Is the number of arguments transmitted to called modules equal to number of
parameters?
5. Are the attributes of arguments transmitted to called modules equal to
attributes of parameters?
6. Is the units system of arguments transmitted to called modules equal to units
system of parameters?
7. Are the number of attributes and the order of arguments to built-in functions
correct?
8. Are any references to parameters not associated with current point of entry?
9. Have input only arguments altered?
10. Are global variable definitions consistent across modules?
11. Are constraints passed as arguments?
12. When a module performs external I/O, additional interface tests must be
conducted.
118
Example Test Checklists
Generic 2
General
1 Does input data vary, including maximum, minimum, and nominal values?
(All alike data, especially all zeroes, is usually a poor choice.)
2 Is erroneous input data used? (All error conditions should be checked.)
3 Do the tests demonstrate that the code completely satisfies each
requirement?
4 Does the actual output match the expected output?
Data-Declaration Error Testing
5 Have all the data structures been explicitly tested?
6 Has all data been properly initialized? (e.g., initialized with the correct data
type, default values)
7 Have all global data structures been tested?
Data Referencing Errors
8 Are all variables set to the proper value or initialized correctly?
119
Automated Approach
Tests are automated through building harnesses and
stubs
Pros
• Tests can be repeated quickly and efficiently as
minor changes are made during development
• No need to select specific test cases to save time
during regression testing
Cons
• has high up front cost, and may be costly to maintain
if the test code is badly designed
• automation is difficult when testing a system with
spaghetti dependencies
120
Planned Approach
• Developer plans to test systematically from the
beginning.
• The plan may involve testing incrementally as classes
are constructed, or to do testing once most or all of
the classes are complete
• When complete, release the module and its test code
for integration with the system
121
Planned Approach
Pros
– tests are documented and can be reviewed and reproduced
– automated tests reduce the expense of regression tests
– a systematic approach means many more bugs are found
early in the development process where they are least
expensive to fix
Cons
– Amount of test code (i.e. test harness and stubs) often
outweighs the “real” module code (i.e. lots more work)
– Changes to released software will usually require updates to
the test-suite
122
Planned Approach
Test planning happens during the module’s design
and implementation
– design for testability
– a “checklist” of things to test is collated during design and
implementation
• a peer or team leader may review the checklist for suitability
and suggest other things to test
– ideally module tests are automated
• reduce duplication by specifying test cases directly in code
• important to ensure that the purpose of each test case is
documented
123
Overview
 White-Box Test Design
 Unit Test Automation
 Unit/Integration Test Issues
– Harnesses & Stubs
124
Test Harnesses
• Supporting code and data used to provide an
environment for testing components of your system.
– Typically used during unit/module test
– Typically created by the developer of the code
– vary between simple user interfaces to allow tests to be
conducted manually, through to fully automated execution of
tests to provide repeatability when the code is modified.
• Building test harnesses may account for 50% of the
total code produced
– valuable asset, and should be controlled in the same way
the code is managed
125
Test Automation Techniques
• code driven
– test cases are embedded directly in the source
code of the test harness
– simple to get tests up and running
– requires little effort for small unchanging modules
– is not easily maintainable for large modules, or
modules were tests are likely to be added a
change frequently
126
Test Automation Techniques
• data driven
– the test harness does not contain any test cases;
instead it reads data from a file that defines the
inputs and expected outputs of each test case
– higher initial overhead in design of interpreter and
data file formats
– initial overhead is quickly recouped by the ease in
adding new tests
127
Data Driven Test Harness
The test harness usually conforms to the following
structure:
while data file is not empty
read inputs and outputs from data file
call function with inputs
if results of function match expected outputs
register TC passed
else
register TC failed
end if
end while
output summary
128
Example - Harness
/* Calculate the hypotenuse of a right angle */
/* triangle . nOpposite and nAdjacent must values */
/* be non negative . Return the hypotenuse or –1 */
/* for invalid input */
double calcHypotenuse ( double nOpposite,
double nAdjacent ) {
if ( nOpposite < 0 or nAdjacent < 0 )
{ return –1; }
return ( sqrt(pow(nOpposite,2)+
pow(nAdjacent,2)) );
}
/* Test Harness – this does all the work */
main(…) {
int count = 0; // count the no of tests executed
int fail = 0;
double result;
…
/* open the input script */
…
while ( line = readLine(inputFile) != EOF ) {
if ( is_comment(line) ) { continue; }
count++;
/* split line into testid,opposite,adjacent,expected */
…
result = calcHypotenuse ( opposite, adjacent );
if ( result != expected ) {
fail++;
output(“Test failed: %s( %d, %d )
got %d expected %dn”,
testid, opposite, adjacent, result, expected );
}
}
/* output the final stats */
output(“Tests run: %dn”, count);
output(“Tests OK: %dn”, count-fail);
output(“Tests failed: %dn”, fail);
}
129
Example - Harness Run
• Sample Input Data
• Sample Output
# format: testid,opposite,adjacent,expected
Test1,3,4,5
Test2,3,4,6 # just to try and force a failure
Test3,-3,4,-1
Test4,4,-1,-1
Test5,0,4,4
Test failed: Test2( 3, 4 ) got 5 expected 6
Tests run: 5
Tests OK: 4
Tests failed: 1
130
Test Stubs
• dummy components that stand in for unfinished
components during unit/module testing and
integration testing.
– quite often code routines that have no or limited internal
processing
• may always return a specific value
• request value from user
• read value from test data file
• simulators may be used as test stubs to mimic other
interfaced systems
131
Test Stubs
• Sometimes code for a low level module is modified to
provide specific control
– E.g. a file I/O driver module may be modified to inject file I/O
errors at specific times, and thus enable the error handing of
I/O errors to be analysed
132
Example - Stub
• Same result for each call
enum Method { GET, POST };
struct response {
int code;
String content;
String header;
};
/* static stub – commonly used since predictable results */
response sendHttpRequest( String url, Method getpost, String params) {
response res;
res.code = 200; /* status OK */
res.content = “<html><title>Hello</title><body>testing</body></html>”;
res.header = “”;
return res;
}
133
Example - Stub
• Lookup result from predefined lookup table or file
/* get value from global lookup table – generated from input script */
response sendHttpRequest( String url, Method getpost, String params) {
response res;
/* assume test input script included data to populate lookup table */
res = lookup(url);
return res;
}
134
Example - Stub
• Conditional response (if file accessible)
/* get value from a file */
response sendHttpRequest( String url, Method getpost, String params) {
response res;
/* assume a file has been opened and filehandle is accessible */
if ( code = readLine(filehandle) ) {
res.code = code;
} else {
res.code = 400; /* fail */
}
if ( content = readLine(filehandle) ) { res.content = content; }
if ( header = readLine(filehandle) ) { res.header = header; }
return res;
}
135
Example - Stub
• Error injection using actual method
• Uses mode (controlled by harness) to determine
whether to inject error
/* get value from a file */
response sendHttpRequest( String url, Method getpost, String params) {
response res;
/* assume a file has been opened and filehandle is accessible */
if ( mode = normal ) {
res = actual_sendHttpRequest(url, getpost, params)
} else {
res.code = 400; /* fail */
}
return res;
}
136
Coordinating Harnesses and
Stubs
TC01:3,4,1998;30;T # normal date
TC02:29,2,1999;28;F # not a leap year
TC03:29,2,2000;29;T # leap year
TC04:29,2,2100;28;F # not a leap year
The data file may have fields indicating data that should be returned by stubbed functions
during the test.
The stubbed functions return global variables that are set by the test harness after
reading the appropriate value from the test file.
For example, the daysInMonth function used by checkDate is stubbed. It returns a pre-
determined value from the test harness data file (shown in bold).
bool checkDate(int d, int m, int y) {
if ( y <= 0 ) return false;
if ( m < 1 || m > 12 ) return false;
if ( d < 1 || d > daysInMonth(m, isLeapYear(y)) )
return false;
return true;
}
137
Coordinating Harnesses and
Stubs (cont)
TC01:3,4,1998;30;T # normal date
TC02:29,2,1999;28;F # not a leap year
TC03:29,2,2000;29;T # leap year
TC04:29,2,2100;28;F # not a leap year
int daysInMonth (int month, bool leapYear) { return globalDaysInMonth; }
int isLeapYear(int y) { return true; } /* simple stub */
while (data remaining in file) {
read data line into (TCID, (d, m, y), globalDaysInMonth, Expected)
if (checkDate(d,m,y) == Expected) {
register (TCID,pass)
else
register (TCID,fail)
}
bool checkDate(int d, int m, int y) {
if ( y <= 0 ) return false;
if ( m < 1 || m > 12 ) return false;
if ( d < 1 || d > daysInMonth(m, isLeapYear(y)) )
return false;
return true;
}
138
Mock Objects
• “Take the place of real objects for testing functionality
that interacts with and is dependent on the real
objects”
Test Driven Development, A Practical Guide,
David Astels, Prentice Hall, 2003
139
Mock Object Example
From Test Driven Development, A Practical Guide,
David Astels, Prentice Hall, 2003
• Takes Die object
• Random behaviour
• Difficult to test with real
object
public class Player {
Die myD20 = null;
public Player(Die d20) {
myD20 = d20;
}
public boolean attack(Orc anOrc) {
if (myD20.roll() > = 13) {
return hit(anOrc);
} else {
return miss();
}
}
private boolean hit(Orc anOrc) {
anOrc.injure(myD20.roll());
return true;
}
private boolean miss() {
return false;
}
}
140
Create Mock Interface
• Extract an interface
from Die
public interface Rollable {
int roll()
}
public class Die implements Rollable {
// …
}
public class Player {
Rollable myD20 = null;
public Player(Rollable d20) {
myD20 = d20;
}
//…
}
141
Create Tests With Mock
• MockDie that always
rolls a certain value is
created
• Test is created with a
MockDie that rolls 10
• Initialise Player with
this MockDie
• Check outcomes with
MockDie
public class MockDie implements Rollable {
private int returnValue;
public MockDie(int constantReturnValue) {
returnValue = constantReturnValue;
}
public int roll() {
return returnValue;
}
}
public void testMiss() {
Rollable d20 = new MockDie(10);
Player badFighter = new Player(d20);
Orc anOrc = new Orc();
assertFalse(“Attack should have missed.”,
badFighter.attack(anOrc));
}
142
Uses of Mock Objects
(and stubs in general)
• To help keep design
decoupled
• To check your code’s usage
of another object
• To test drive your code from
the inside out
• To make your code run faster
• To make your code easier to
develop code that interacts
with hardware devices,
remote systems, and other
problematic resources
• To defer having to implement
a class
• To let us test-drive
components in isolation from
the rest of the system
• To promote interface-based
design
• To promote composition over
inheritance
• To refine interfaces
• To test unusual, unlikely and
exceptional situations
Test Driven Development, A Practical Guide, David Astels, Prentice Hall, 2003

More Related Content

More from nazeer pasha

Doe Taguchi Basic Manual1
Doe Taguchi Basic Manual1Doe Taguchi Basic Manual1
Doe Taguchi Basic Manual1nazeer pasha
 
Teaching Testing Qw%202001
Teaching Testing Qw%202001Teaching Testing Qw%202001
Teaching Testing Qw%202001nazeer pasha
 
Software Testing Guide
Software Testing GuideSoftware Testing Guide
Software Testing Guidenazeer pasha
 
Cstp Certification Compare
Cstp Certification CompareCstp Certification Compare
Cstp Certification Comparenazeer pasha
 
Blackboxtesting 02 An Example Test Series
Blackboxtesting 02 An Example Test SeriesBlackboxtesting 02 An Example Test Series
Blackboxtesting 02 An Example Test Seriesnazeer pasha
 
Exploratory Testing
Exploratory TestingExploratory Testing
Exploratory Testingnazeer pasha
 
Testing Types And Models
Testing Types And ModelsTesting Types And Models
Testing Types And Modelsnazeer pasha
 
Swe3643 2006 Decision Table Based Testing
Swe3643 2006 Decision Table Based TestingSwe3643 2006 Decision Table Based Testing
Swe3643 2006 Decision Table Based Testingnazeer pasha
 
Software Engineering Fundamentals Svetlin Nakov
Software Engineering Fundamentals Svetlin NakovSoftware Engineering Fundamentals Svetlin Nakov
Software Engineering Fundamentals Svetlin Nakovnazeer pasha
 
Exploring Exploratory Testing
Exploring Exploratory TestingExploring Exploratory Testing
Exploring Exploratory Testingnazeer pasha
 
Exploratory Testing
Exploratory TestingExploratory Testing
Exploratory Testingnazeer pasha
 

More from nazeer pasha (20)

Doe Taguchi Basic Manual1
Doe Taguchi Basic Manual1Doe Taguchi Basic Manual1
Doe Taguchi Basic Manual1
 
Teaching Testing Qw%202001
Teaching Testing Qw%202001Teaching Testing Qw%202001
Teaching Testing Qw%202001
 
Orth Arrays
Orth ArraysOrth Arrays
Orth Arrays
 
Testing
TestingTesting
Testing
 
Tc Checklist
Tc ChecklistTc Checklist
Tc Checklist
 
Software Testing Guide
Software Testing GuideSoftware Testing Guide
Software Testing Guide
 
Cstp Certification Compare
Cstp Certification CompareCstp Certification Compare
Cstp Certification Compare
 
Blackboxtesting 02 An Example Test Series
Blackboxtesting 02 An Example Test SeriesBlackboxtesting 02 An Example Test Series
Blackboxtesting 02 An Example Test Series
 
Exploratory Testing
Exploratory TestingExploratory Testing
Exploratory Testing
 
Chanakya Niti
Chanakya NitiChanakya Niti
Chanakya Niti
 
Testing
TestingTesting
Testing
 
Testing Types And Models
Testing Types And ModelsTesting Types And Models
Testing Types And Models
 
Swtesting
SwtestingSwtesting
Swtesting
 
Testing Framework
Testing FrameworkTesting Framework
Testing Framework
 
Testing
TestingTesting
Testing
 
Swe3643 2006 Decision Table Based Testing
Swe3643 2006 Decision Table Based TestingSwe3643 2006 Decision Table Based Testing
Swe3643 2006 Decision Table Based Testing
 
Softwaretesting
SoftwaretestingSoftwaretesting
Softwaretesting
 
Software Engineering Fundamentals Svetlin Nakov
Software Engineering Fundamentals Svetlin NakovSoftware Engineering Fundamentals Svetlin Nakov
Software Engineering Fundamentals Svetlin Nakov
 
Exploring Exploratory Testing
Exploring Exploratory TestingExploring Exploratory Testing
Exploring Exploratory Testing
 
Exploratory Testing
Exploratory TestingExploratory Testing
Exploratory Testing
 

Unit Testing

  • 1. $ÆD$Hè#A=A=’”ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è?=è?= Ëè-èC=$‹Ì‰d$0RèùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËèÆD$pèF=ÇD-èC=$‹Ì‰d$0Rè BW‹ÎètÆD$pèF=ÇD==ÿèƒÇÿÿÿÿ‹t$j‹Îèc<=PT$QD$ RPL$@èTþÿÿL$èÛ:=QRL$4è¸ýÿÿ ‹D$…À~AD$4L$PT$QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0R èùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËè-C=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ G=Æ $hØ#PRŒ$€ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è ™êÿÿ‹N4jèßêËè-èC=$‹Ì‰d$0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-ÿÿPL$Æ D$Hè#A=A=’”ÃèV@=”Ãè@=èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$ è“9=;Öt‹ASW‹°‹< ‰ ‹A‰<°_[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê Áé ó¥‹Èƒáó¤¾ìêøê  Æ„$¤ ’Æ„$¤Æ„èÛ:=$¤ÆD$pèF=ÇD‹Ì‰dÆD$pèF=ÇD$,PèŽ G=ÆD$hØ#PèÛ:=RŒ$€ ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™ê[|,L$LT$PQ h$èƒ?=è?=è?=-Ëè-èC=$‹ÌèÛ:=‰d$0RèùB>=$->=$L$(ÆD$DèÆèÛ:=D$pèF=ÇD¾==è°= =‹|$PËè-èC=$‹Ëè-èC=$‹Ì‰d$0RèùBÿÿ‹N4jèßêÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A= -óÿÿPL$ÆD$Hè#A=A=’”ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è? =è?=-Ëè-èC=$‹Ì‰d$0RèùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËèÆD$pèF=ÇD-èC=$‹Ì‰d$0 RèùBW‹ÎètÆD$pèF=ÇD==ÿèƒÇÿÿÿÿ‹t$j‹Îèc<=PT$QD$ RPL$@èTþÿÿL$èÛ:=QRL$4è¸ýÿ ÿ‹D$…À~AD$4L$PT$QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0Rè ùB>=$-=$L$(ÆD$Dè¾==è°==‹|$PËè-èC=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ G=ÆD$hØ #PRŒ$€ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™êÿÿ‹N 4jèßêËè-èC=$‹Ì‰d$0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-PL$ÆD$Hè#A=A=’” ÃèV@=”Ãè@=èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$è“9=;Öt‹ASW‹°‹<  ‰ ‹A‰<°_[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê Áé ó¥‹Èƒáó¤¾ìêøê Æ„$¤ ’Æ„$¤Æ„èÛ :=$¤ÆD$pèF=ÇD‹Ì‰dÆD$pèF=ÇD$,PèŽ G=ÆD$hØ#PèÛ:=RŒ$€ÆD$t è4F=ÆD$pèF= ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™ê[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$ ‹ÌèÛ:=‰d$0RèùB>=$->=$L$(ÆD$DèÆèÛ:=D$pèF=ÇD¾==è°==‹|$PËè-èC=$‹Ëè-èC=$‹Ì‰ d$0RèùBÿÿ‹N4jèßêÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-óÿÿPL$ÆD$Hè#A=A=’” ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0R èùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËèÆD$pèF=ÇD-èC=$‹Ì‰d$0RèùBW‹ÎètÆD$pèF= D==ÿèƒÇÿÿÿÿ‹t$j‹Îèc<=PT$QD$ RPL$@èTþÿÿL$èÛ:=QRL$4è¸ýÿÿ‹D$…À~AD$4L$PT$ QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0RèùB>=$->=$L$(ÆD$Dè ==è°==‹|$PËè-èC=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ G=ÆD$hØ#PRŒ$€ÆD$t è4F= ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™êÿÿ‹N4jèßêËè-èC=$‹Ì‰d$ 0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-óÿÿPL$ÆD$Hè#A=A=’”ÃèV@=”Ãè@= èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$è“9=;Öt‹ASW‹°‹< ‰ ‹A‰<° _[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê Áé ó¥‹Èƒáó¤¾ìêøêÆ„$¤ ’Æ„$¤Æ„èÛ:=$¤ÆD$pèF=ÇD $ÆD$Hè#A=A=’”ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è?=è?= Ëè-èC=$‹Ì‰d$0RèùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËèÆD$pèF=ÇD-èC=$‹Ì‰d$0Rè BW‹ÎètÆD$pèF=ÇD==ÿèƒÇÿÿÿÿ‹t$j‹Îèc<=PT$QD$ RPL$@èTþÿÿL$èÛ:=QRL$4è¸ýÿÿ ‹D$…À~AD$4L$PT$QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0R èùB>=$->=$L$(ÆD$Dè¾==è°==‹|$PËè-C=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ G=Æ $hØ#PRŒ$€ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è ™êÿÿ‹N4jèßêËè-èC=$‹Ì‰d$0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-ÿÿPL$Æ D$Hè#A=A=’”ÃèV@=”Ãè@=èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$ è“9=;Öt‹ASW‹°‹< ‰ ‹A‰<°_[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê Áé ó¥‹Èƒáó¤¾ìêøê  Æ„$¤ ’Æ„$¤Æ„èÛ:=$¤ÆD$pèF=ÇD‹Ì‰dÆD$pèF=ÇD$,PèŽ G=ÆD$hØ#PèÛ:=RŒ$€ ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™ê[|,L$LT$PQ h$èƒ?=è?=è?=-Ëè-èC=$‹ÌèÛ:=‰d$0RèùB>=$->=$L$(ÆD$DèÆèÛ:=D$pèF=ÇD¾==è°= =‹|$PËè-èC=$‹Ëè-èC=$‹Ì‰d$0RèùBÿÿ‹N4jèßêÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A= -óÿÿPL$ÆD$Hè#A=A=’”ÃèV@=”Ãè@=èä?=RPˆÆD$pèF=ÇD$Pè[|,L$LT$PQh$èƒ?=è? ‹D$…À~AD$4L$PT$QDèÛ:=$ RPL$@è“[|,L$LT$PQh$èƒ?=è?=è?=-Ëè-èC=$‹Ì‰d$0Rè ùB>=$-=$L$(ÆD$Dè¾==è°==‹|$PËè-èC=$‹þÿÿL$ èš:=QRL$4è̉dèÛ:=$,PèŽ G=ÆD$hØ #PRŒ$€ÆD$t è4F=ÆD$pèF=ÇD$(DjRÿüñ‚‹Èèäçÿÿë3À‹L$H‹QR‹ÈÆD$@‰F4è™êÿÿ‹N 4jèßêËè-èC=$‹Ì‰d$0RèùBÿÿ…Àu8hV‹Ëè-èC=$‹Ì‰d$0RèùB=B=‘A=-PL$ÆD$Hè#A=A=’” ÃèV@=”Ãè@=èä·ýÿÿ‹D$…À¿èÛ:=¸$”ÆD$pèF=ÇD:=$j/L$0è :=L$,ˆ$$è“9=;Öt‹ASW‹°‹<  ‰ ‹A‰<°_[^Âó«‹„$4_^3À[ÄÇD$ RSÿ ìê Áé ó¥‹Èƒáó¤¾ìêøê Æ„$¤ ’Æ„$¤Æ„èÛ :=$¤ÆD$pèF=ÇD‹Ì‰dÆD$pèF=ÇD$,PèŽ G=ÆD$hØ#PèÛ:=RŒ$€ÆD$t è4F=ÆD$pèF= Unit Testing Software Quality Principles Dr Danny Powell K. J. Ross & Associates Pty. Ltd. Suite 4, Ground Floor 13a Narrabang Way Belrose NSW 2085 Telephone: 02 9450 2333 Facsimile: 02 9450 2744 Mobile: 0404 922 177 Email: dannyp@kjross.com.au http//www.kjross.com.au
  • 2. 2 Test Driven Development • http://www.testdriven.com/ “Test driven development (TDD) is emerging as one of the most successful developer productivity enhancing techniques to be recently discovered. The three-step: write test, write code, refactor – is a dance many of us are enjoying.”
  • 3. 3 Overview  White-Box Test Design  Unit Test Automation  Unit/Integration Test Issues
  • 4. 4 Overview  White-Box Test Design – Statement, Branch and Path Coverage – Loop Testing – Decision Coverage – Data Flow Coverage  Unit Test Automation  Unit/Integration Test Issues
  • 5. 5 White-Box Testing • Common goal to exercise every path through a program – Infeasible to do this • Techniques for selecting paths to test. • Often associated with test coverage metrics – Measure the percentage of paths of the selected type that are exercised by test cases. – Target coverage levels are set to guide how thoroughly a program must be tested.
  • 6. 6 White-Box Testing • White-box testing works at the code level – The structure of the code is analysed to propose test cases – Test paths are proposed based on the structure
  • 7. 7 Overview  White-Box Test Design – Statement, Branch and Path Coverage – Loop Testing – Decision Coverage – Data Flow Coverage – LCSAJ Coverage – Pros and Cons  Unit Test Automation  Unit/Integration Test Issues
  • 8. 8 Statement, Branch and Path Coverage A K B D E H C F G I if A then if B then D else E end if; H else if C then F else G end if; I end if
  • 9. 9 Statement Coverage • Each statement in the program visited by a test – 10 statements A K B D E H C F G I          
  • 10. 10 Branch Coverage • Each branch in the logic visited by a test – 6 branches A K B D E H C F G I      
  • 11. 11 Path Coverage • Each path through the logic visited by a test – 4 paths A K B D E H C F G I    
  • 12. 12 Test Case • Execute test case and evaluate statements, branches and paths visited – test visits: A, B, D, H, K – statement coverage • 5/10 = 50% – branch coverage • 2/6 = 33% – path coverage • 1/4 = 25% A K B D E H C F G I
  • 13. 13 Statement, Branch and Path Coverage Differences Statement coverage without branch coverage Statement and branch coverage without path coverage A B C A B C D E F G • 100% branch coverage gives 100% statement coverage • 100% path coverage gives 100% branch coverage
  • 14. 14 Coverage Test Design • Steps – Analyse source code to derive flow graph – Propose coverage test paths on flow graph – Evaluate source code conditions to achieve each path – Propose input and output values based on conditions
  • 15. 15 Binary Search procedure Binary_Search (Key : ELEM; Table : ELEM_ARRAY; Found : in out BOOLEAN; Row : in out ELEM_INDEX ) is - - Assume that Table’FIRST and Table’LAST are both greater - - than or equal to zero and Table’LAST >= Table’FIRST Bot : ELEM_INDEX := Table’FIRST; Top : ELEM_INDEX := Table’LAST; Mid : ELEM_INDEX; begin Row := (Table’FIRST + Table’LAST) div 2; Found := Table(Row) = Key; while Bot <= Top and not Found loop Mid := (Top + Bot) div 2; if T( Mid ) = Key then Found := true; Row := Mid; elsif T( Mid ) < Key then Bot := Mid + 1; else Top := Mid – 1; end if; end loop; end Binary_Search; A I B C D H E G F while Bot <= Top and not Found if T(Mid) = Key then if T(Mid) < Key then J
  • 16. 16 Sample Run Start Loop 0 1 2 3 4 5 6 7 8 9 10 T = Key = 6 1 2 3 4 5 6 7 8 9 10 T = Bot Row Top T(Row) = 5 Found = FALSE Key = 6
  • 17. 17 Sample Run Loop 1 1 2 3 4 5 6 7 8 9 10 T = Bot L, Mid Top T(Mid) = 5 Found = FALSE Key = 6
  • 18. 18 Sample Run Loop 2 1 2 3 4 5 6 7 8 9 10 T = Bot Row Top T(Mid) = 8 Found = FALSE Key = 6 Mid
  • 19. 19 Sample Run Loop 3 Exit Program (Found = TRUE; Row = 6) 1 2 3 4 5 6 7 8 9 10 T = Bot, Mid, Row Top T(Mid) = 6 Found = TRUE Key = 6 Row = 6
  • 20. 20 Propose Coverage Paths • Come up with simple test cases that look at different areas of coverage separately. – For example, start with a simple single iteration of the loop - 1 search to the left (<)  A, B, C, E, G, H, J, B, C, D, J, B, I – This leaves only a path that visits node F to achieve 100% path coverage  A, B, C, E, F, H, J, B, C, D, J, B, I • Use black-box techniques to propose initial cases and review paths
  • 21. 21 Proposing Test Cases • It is possible to work backwards from a path to obtain a test case, but it takes some analysis – May be necessary when your guesses at test cases still aren’t covering the path you require • You need to develop an understanding of the conditions in the program that force a particular path to be taken – Must be able to trace the path through the program and record the decisions that are made to stay on the path.
  • 22. 22 Propose Coverage Paths • One path can provide 100% statement and branch coverage (100% path coverage is not feasible): A, B, C, E, F, H, J, B, C, E, G, H, J, B, C, D, J, B, I – This path corresponds to the example illustrated above. A I B C D H E G F while Bot <= Top and not Found if T(Mid) = Key then if T(Mid) < Key then J
  • 23. 23 Propose Coverage Paths • Some combinations of paths in the graph will not be achievable within the program – E.g. the following gives 100% statement and branch coverage  A, B, C, D, J, B, C, E, F, H, J, B, C, E, G, H, J, B, I – This path is not possible • B, C, D, J can’t happen first A I B C D H E G F while Bot <= Top and not Found if T(Mid) = Key then if T(Mid) < Key then J
  • 24. 24 Review of Coverage Example • Difficult to determine what paths are feasible and test case values to satisfy paths – Requires solid understanding of the program logic – Easier to have a number of smaller paths – Typical to first apply black-box testing, measure coverage, and then use white-box testing to gain further coverage • Sufficiency of test case questionable – Didn’t consider both conditions on the while loop • Possible to separate the conditions as two decisions in the flow graph – Didn’t cover loops in detail
  • 25. 25 Overview  White-Box Test Design – Statement, Branch and Path Coverage – Loop Testing – Decision Coverage  Unit Test Automation  Unit/Integration Test Issues
  • 26. 26 Loop Testing • Loops easily lead to programs in which it is not feasible to test all paths – Combinatorial explosion • Basis paths provide mechanism to tackle path testing involving loops • Zero-path – Represents short circuit of the loop • One-path – Represent a loop in which only one iteration is performed – Basis paths represents atomic components of all paths • Possible paths are combinations and sequences of basis paths
  • 27. 27 Basis Path Testing • Each basis path is exercised by at least one test – Both for zero-path and one-path basis paths • Combinations and sequences of basis paths do not need to be exercised by a test – They are covered by combinations and sequences of already tested basis paths
  • 28. 28 Basis Path Example • Binary_Search – Basis Paths • Zero-paths – A, B, I • One-paths – B, C, D, J – B, C, E, F, H, J – B, C, E, G, H, J A I B C D H E G F while Bot <= Top and not Found if T(Mid) = Key then if T(Mid) < Key then J
  • 29. 29 Review of Basis Path Testing • Doesn’t consider – Proper loop termination (e.g. reaching maximum value) – Switching between conditions used in each iteration
  • 30. 30 Beizer’s Loop Tests [Bei95a] • A number of other iteration test categories: Bypass: any value that causes loop to be exited immediately Once: values that cause the loop to be executed exactly once Twice: values that cause the loop to be executed exactly twice Typical: a typical number of iterations Max: the maximum number of allowed iterations Max + 1: one more than the maximum allowed Max - 1: one less than the maximum allowed Min: the minimum number iterations required Min + 1: one more than the minimum required Min - 1: one less than the minimum required Null: one with a null or empty value for number of iterations Negative: one with a negative value for number of iterations • Some cases may overlap – e.g. Bypass with Min/Null/Negative, etc.
  • 31. 31 Overview  White-Box Test Design – Statement, Branch and Path Coverage – Loop Testing – Decision Coverage  Unit Test Automation  Unit/Integration Test Issues
  • 32. 32 Branch Condition Testing • Identifies individual boolean operands within decisions • Tests exercise individual and combinations of boolean operand values • Example: if A or (B and C) then do_something else do_something_else
  • 33. 33 Branch Condition Coverage • Each operand is tested with values of TRUE and FALSE – Example’s operands • A, B and C – Weaknesses • Can often be achieved with just two cases • Can often be achieved without exercising both decision outcomes Case A B C 1 FALSE FALSE FALSE 2 TRUE TRUE TRUE Case A B C 1 TRUE FALSE FALSE 2 FALSE TRUE TRUE
  • 34. 34 Branch Condition Combination Coverage • All combination of boolean operand values Case A B C 1 FALSE FALSE FALSE 2 TRUE FALSE FALSE 3 FALSE TRUE FALSE 4 TRUE TRUE FALSE 5 FALSE FALSE TRUE 6 TRUE FALSE TRUE 7 FALSE TRUE TRUE 8 TRUE TRUE TRUE • Requires 2n cases for n operands for 100% coverage • Rapidly becomes infeasible for more complex conditions
  • 35. 35 Modified Condition Decision Coverage • Pragmatic compromise that requires fewer test cases than branch condition combination – Used widely in avionics software • Required by RTCA/DO-178B • Show that each boolean operand can independently affect the decision outcome
  • 36. 36 Modified Condition Decision Coverage • Decision outcome = A or (B and C) Case A B C Outcome A1 FALSE FALSE TRUE FALSE A2 TRUE FALSE TRUE TRUE Case A B C Outcome B1 FALSE FALSE TRUE FALSE B2 FALSE TRUE TRUE TRUE Case A B C Outcome C1 FALSE TRUE FALSE FALSE C2 FALSE TRUE TRUE TRUE
  • 37. 37 Modified Condition Decision Coverage • Minimal tests: A1 & B1 same, B2 & C1 same • 100% coverage requires – minimum of n+1 test cases – maximum of 2n test cases Case A B C Outcome 1 (A1, B1) FALSE FALSE TRUE FALSE 2 (A2) TRUE FALSE TRUE TRUE 3(B2, C2) FALSE TRUE TRUE TRUE 4 (C1) FALSE TRUE FALSE FALSE
  • 38. 38 Condition Coverage Issues • Placement of boolean conditions outside decision FLAG := A or (B and C) if FLAG then … – Variation is to test for all boolean expressions • Compiler optimisation – C and C++ short-circuits && and || – Not possible to show coverage • Other decision structures – Case and switch statements
  • 39. 39 White-Box Techniques Conclusions • Useful for analysing particular paths in programs to exercise them with tests • Gives rise to large number of test cases • Used in conjunction with black-box techniques – Look for unexecuted parts of program • Techniques are also useful when applied as black- box techniques – Specification involving logic are used in place of source code (e.g. flow chart; transaction scenario diagram)
  • 40. 40 Pros and Cons of White-Box Testing Advantages – Easier to identify decisions, and equivalence classes that are being used in the logic than with black-box testing – More objective than black box testing, different people deriving test cases will arrive at corresponding results – Automated tools available to propose paths to test and to monitor coverage as the code is tested
  • 41. 41 Pros and Cons of White-Box Testing Disadvantages - Incorrect code gives rise to tests that do not conform to expected operation as well - Can’t detect wrong function being implemented, or missing functions or code. - Need to have a good understanding of the code to understand the meaning of each test path through the code - Some paths are difficult to visit - Doesn’t consider interfacing issues - Need access to the code
  • 42. 42 Pros and Cons of White-Box Testing More disadvantages - Impossible to test “spaghetti code” or “pacincko code” as there are excessive numbers of paths - Problems with multiple processes, threads, interrupts, event processing - Dynamically changing data and code is difficult to analyse - Only practical at low levels, for whole systems the number of paths through a whole program is incredibly large
  • 43. 43 • How could white-box techniques be applied to your black-box testing approaches? Discussion
  • 44. 44 Overview  White-Box Test Design  Unit Test Automation – Unit Test Frameworks – Unit Test Tools  Unit/Integration Test Issues
  • 45. 45 Overview  White-Box Test Design  Unit Test Automation – Unit Test Frameworks – Unit Test Tools  Unit/Integration Test Issues
  • 46. 46 Unit Test Frameworks • Provides the test scaffolding around the code under development • Available tools: – Commercial Tools • Jtest, Cantata, etc. – Extreme Programming frameworks (OpenSource) (http://c2.com/cgi/wiki?TestingFramework) • Junit, HTTPUnit, DelphiUnit, CppUnit, PerlUnit, PhPUnit, etc.
  • 47. 47 JUnit • Java (code-level) regression testing framework – Written by Erich Gamma & Kent Beck • See www.junit.org • Open Source • Many extensions and documentation
  • 48. 48 Building JUnit Tests 1. Define a subclass of TestCase 2. Override the setUp() method to initialise objects under test 3. Override the tearDown() method to release objects under test 4. Define one or more testXXX() methods to exercise objects under test 5. Define a suite() factory method the creates all the testXXX() methods or the TestCase 6. Define a main() method to run the TestCase
  • 49. 49 Case Study - Money Class class Money { private int fAmount; private String fCurrency; public Money(int amount, String currency) { fAmount= amount; fCurrency= currency; } public int amount() { return fAmount; } public String currency() { return fCurrency; } public Money add(Money m) { return new Money(amount()+m.amount(), currency()); } }
  • 50. 50 Case Study - Test Case public class MoneyTest extends TestCase { //… public void testSimpleAdd() { Money m12CHF= new Money(12, CHF"); Money m14CHF= new Money(14, "CHF"); Money expected= new Money(26, "CHF"); Money result=m12CHF.add(m14CHF); assert(expected.equals(result)); } } Object Creation Method Under Test Result Verification assert - check boolean result is true Junit Test Case • Need an equals method in Money
  • 51. 51 Case Study - Test Case • Create test for Equals first public void testEquals() { Money m12CHF= new Money(12, "CHF"); Money m14CHF= new Money(14, "CHF"); assert(!m12CHF.equals(null)); assertEquals(m12CHF, m12CHF); assertEquals(m12CHF, new Money(12, "CHF")); assert(!m12CHF.equals(m14CHF)); } Result Verification assertEquals - compare two values
  • 52. 52 Case Study - Optimised Test Cases public class MoneyTest extends TestCase { private Money f12CHF; private Money f14CHF; protected void setUp() { f12CHF= new Money(12, "CHF"); f14CHF= new Money(14, "CHF"); } public void testEquals() { assert(!f12CHF.equals(null)); assertEquals(f12CHF, f12CHF); assertEquals(f12CHF, new Money(12, "CHF")); assert(!f12CHF.equals(f14CHF)); } public void testSimpleAdd() { Money expected= new Money(26, "CHF"); Money result= f12CHF.add(f14CHF); assert(expected.equals(result)); } } • setUp & tearDown methods available to manage objects
  • 53. 53 Case Study - Test Suite public static Test suite() { TestSuite suite= new TestSuite(); suite.addTest(new MoneyTest("testEquals")); suite.addTest(new MoneyTest("testSimpleAdd")); return suite; } • Suite is a static method • Test cases are added to the suite
  • 54. 54 Case Study - Running Tests /** * Uncomment choice of UI **/ public static void main() { String[] testCaseName = {MoneyTest.class.getName()}; // junit.textui.TestRunner.main(testCaseName); // junit.swingui.TestRunner.main(testCaseName); junit.ui.TestRunner.main(testCaseName); } • Choice of: • Textual UI • Swing UI • AWT UI
  • 55. 55 JUnit • Reports failures - expected and actual • Summarises outcomes
  • 56. 56 • JUnit • Ant • JCoverage • Cruise Control Demonstration
  • 57. 57 Ant • http://jakarta.apache.org/ant/index.html • Similar to make • Cross-platform • Defacto standard for Java builds • Support for continuous integration: – Build – Test – Documentation – Package – Deploy • NAnt – similar framework on .Net
  • 58. 58 Code Coverage • Shows code visited after completing tests • Screen shot of Jcoverage (GPL) • www.jcoverage.com
  • 59. 59 Code Coverage • Drill down to view the Class code • Graphically shows the code missed in the listing
  • 60. 60 Cruise Control http://cruisecontrol.sourceforge.net/ • CruiseControl is a framework for a continuous build process • It includes – plugins for email notification – Ant – various source control tools – Web interface is provided to view the details of the current and previous builds • Also CruiseControl.NET
  • 64. 64 Unit Test Organisation • Create the tests in the same package as the code under test • For each Java package in the application, define a TestSuite class that contains all the tests for verifying the class • Make sure the build process includes the compilation of all test suites and test cases
  • 65. 65 Unit Test Principles • Code a little, test a little, code a little, test a little • Run tests as often as possible, at least as often as you run compiler • Run all the tests in the system at least once per day • Begin by writing tests for the area of code that your most worried about breaking • Write tests that have highest possible return on your testing investment • When you need to add new functionality, add the tests first • If you find yourself debugging using println, write a test case instead • When a bug is reported, write a test case to expose the bug • Next time someone asks for help debugging, write a test case to expose the bug • Don’t deliver code that doesn’t pass all the tests
  • 66. 66 Other Frameworks http://c2.com/cgi/wiki?TestingFramework • AsUnit - Action Script • ASPUnit - ASP using VB • CPPUnit - C++, C# • CuUnit - VisualC++ • COMUnit • DelphiUnit • DotNetUnit, DotUnit - .net • EiffelUnit • ForteUnit • JsUnit - Javascript • LingoUnit • Nunit, NUnitASP, NUnitForms • PerlUnit • PhPUnit • PLSQLUnit - Oracle • PowerBuilderUnit • PythonUnit • SmallTalkUnit • VBUnit • VBAUnit • XMLUnit • XSLTUnit
  • 67. 67 HTTP Unit • Free, Opensource JAVA API • Accesses web sites without browser • Combined with Junit • framework for web testing • Designed and implemented by Russell Gold
  • 68. 68 HTTP Unit WebConversation wc = new WebConversation(); WebRequest req = new GetMethodWebRequest("http://www.meterware.com/testpage.html" ); WebResponse resp = wc.getResponse( req ); • WebConversation class • Takes the place of a browser talking to a single site • Maintains session context, which it does via cookies returned by the server • Response manipulated either as pure text (via the toString() method), as a DOM (via the getDOM() method), or by using the various other methods WebConversation wc = new WebConversation(); WebResponse resp = wc.getResponse( "http://www.meterware.com/testpage.html" );
  • 69. 69 HTTP Unit WebConversation wc = new WebConversation(); // read page WebResponse resp = wc.getResponse( "http://httpunit.sourceforge.net/doc/Cookbook.html" ); // find the link WebLink link = resp.getLinkWith( "response" ); // convert it to a request WebRequest req = link.getRequest(); // retrieve the referenced page WebResponse jdoc = wc.getResponse( req ); • Navigation • Retrieve and follow links • Image links can be followed • WebResponse.getLinkWithImageText()
  • 70. 70 HTTP Unit // select the first form in the page WebForm form = resp.getForms()[0]; assertEquals( "La Cerentolla", form.getParameterValue( "Name" ) ); assertEquals( "Chinese", form.getParameterValue( "Food" ) ); assertEquals( "Manayunk", form.getParameterValue( "Location" ) ); assertEquals( "on", form.getParameterValue( "CreditCard" ) ); • Form evaluation • Properties • Submit request = form.getRequest(); request.setParameter( "Food", "Italian" ); request.removeParameter( "CreditCard" ); response = wc.getResponse( request );
  • 71. 71 HTTP Unit WebTable table = resp.getTables()[0]; assertEquals( "rows", 4, table.getRowCount() ); assertEquals( "columns", 3, table.getColumnCount() ); assertEquals( "links", 1, table.getTableCell( 0, 2 ).getLinks().length ); • Table evaluation • Properties • Content String[][] colors = resp.getTables()[1].asText(); assertEquals( "Name", colors[0][0] ); assertEquals( "Color", colors[0][1] ); assertEquals( "gules", colors[1][0] ); assertEquals( "red", colors[1][1] ); assertEquals( "sable", colors[2][0] ); assertEquals( "black", colors[2][1] ); name color gules red sable black
  • 72. 72 HTML Unit • Like HTTP Unit • Extensions for supporting Javascript (latest version) – Uses Apache Rhino javascript interpreter
  • 73. 73 SQLUnit http://sqlunit.sourceforge.net • Regression and unit testing harness for testing database stored procedures. • Test suite written as an XML file. • The SQLUnit harness is written in Java – Uses the JUnit unit testing framework to convert the XML test specifications to JDBC calls and compare the results generated from the calls with the specified results. – It should be possible, at least in theory, to write unit tests for stored procedures for any database that provides a JDBC driver.
  • 74. 74 SQLUnit GUI Tool • Generates test <test name="Checking returned value from customer"> <sql> <stmt>select custId from customer where custId=?</stmt> <param id="1" type="INTEGER" inout="in" is-null="false"> 1</param> </sql> <result><resultset id="1"> <row id="1"><col id="1" type="INTEGER">1</col></row> </resultset></result> </test>
  • 75. 75 SQLUnit Output Buildfile: build.xml init: test-ant-task: [sqlunit] Getting connection... [sqlunit] Setting up test... [sqlunit] Running test[1]: Adding department HR [sqlunit] Running test[2]: Adding department InfoTech using non-Callable form [sqlunit] Running test[3]: Adding Employee John Doe to InfoTech [sqlunit] Running test[4]: Adding John Doe again [sqlunit] Running test[5]: Adding Jane Doe to HR [sqlunit] Running test[6]: Adding Dick Tracy to InfoTech [sqlunit] Running test[7]: Updating Hourly Rate for John [sqlunit] Running test[8]: Looking up John Doe by name [sqlunit] Running test[9]: Looking up all employees in InfoTech [sqlunit] Running test[10]: Adding timecard for John [sqlunit] Running test[11]: Adding another timecard for John [sqlunit] Running test[12]: Adding timecard for Dick
  • 76. 76 [sqlunit] Running test[13]: Getting monthly report for InfoTech [sqlunit] No match on variable at [rset,row,col]=([1,1,4] [sqlunit] *** expected: [sqlunit] <result> [sqlunit] <resultset id="1"> [sqlunit] <row id="1"> [sqlunit] <col id="1" type="VARCHAR">Information Technology</col> [sqlunit] <col id="2" type="VARCHAR">John Doe</col> [sqlunit] <col id="3" type="INTEGER">16</col> [sqlunit] <col id="4" type="NUMERIC">56.00</col> [sqlunit] <col id="5" type="NUMERIC">880.00</col> [sqlunit] </row> [sqlunit] <row id="2"> [sqlunit] </row> sqlunit] </resultset> [sqlunit] </result> [sqlunit] *** but got: [sqlunit] <result> [sqlunit] <resultset id="1"> [sqlunit] <row id="1"> [sqlunit] <col id="1" type="VARCHAR">Information Technology</col> [sqlunit] <col id="2" type="VARCHAR">John Doe</col> [sqlunit] <col id="3" type="INTEGER">16</col> [sqlunit] <col id="4" type="NUMERIC">55.00</col> [sqlunit] <col id="5" type="NUMERIC">880.00</col> [sqlunit] </row> [sqlunit] </resultset> [sqlunit] </result> [sqlunit] Tearing down test... [sqlunit] Time: 1.204 [sqlunit] OK (1 tests) [sqlunit] BUILD SUCCESSFUL Total time: 2 seconds
  • 77. 77 DBUnit http://dbunit.sourceforge.net • JUnit extension that puts your database into a known state between test runs – Helps you avoid the problems that can occur when one test corrupts the database and causes subsequent tests to fail or give faulty results. – It can read the contents of a table and store it to XML using a FlatXmlDataSet
  • 78. 78 DBUnit • Table data saved as XML for restore during testing <EMPLOYEE employee_uid='1‘ start_date='2001-01-01‘ first_name='Andrew‘ ssn=‘000-29-2030‘ last_name='Glover‘ />
  • 80. 80 Nunit Example StackTest.cs • See Book Chapter http://richclients.org/files/newkirk/TDD%20in%20Microsoft%20.NET%20Chapter%202.pdf using System; using NUnit.Framework; [TestFixture] public class StackFixture { private Stack stack; [SetUp] public void Init() { stack = new Stack(); } [Test] public void Empty() { Assert.IsTrue(stack.IsEmpty); } [Test] public void PushOne() { stack.Push(“first element”); Assert.IsFalse(stack.IsEmpty, “After Push, IsEmpty should be false”); } [Test] public void Pop() { stack.Push(“first element”); stack.Pop(); Assert.IsTrue(stack.IsEmpty, “After Push - Pop, IsEmpty should be true”); } … …
  • 81. 81 Nunit Example Stack.cs using System; using System.Collections; public class Stack { private ArrayList elements = new ArrayList(); public bool IsEmpty { get { return (elements.Count == 0); } } public void Push(object element) { elements.Insert(0, element); } public object Pop() { object top = Top(); elements.RemoveAt(0); return top; } public object Top() { if(IsEmpty) throw new InvalidOperationException( “Stack is Empty”); return elements[0]; } }
  • 82. 82 • What are the perceived pros and cons of test driven development, continuous integration, and iterative releases • Develop a checklist of recommendations – areas to encourage – areas to avoid Discussion
  • 83. 83 • Review other Junit tools on www.junit.org Discussion
  • 84. 84 Overview  White-Box Test Design  Unit Test Automation – Unit Test Frameworks – Unit Test Tools  Unit/Integration Test Issues
  • 85. 85 Tools to Aid in Testing • Debugger – e.g. softice • test coverage – e.g TCMON, PureCoverage, Numega, ATTOL, C-Cover, CTC++, TCAT • memory analysis (usage, leaks, etc) – e.g. BoundsChecker, Purify, GlowCode, • Performance – e.g. Quantify, Jprobe • Integrated – Cantata, AdaTest, JTest, VectorCAST See Source Tools at http://www.aptest.com/resources.html
  • 86. 86 Testing with a Debugger • In general, a slow, labour-intensive way to test • Should not be used to test new developments – A proper test suite may take longer to create but when regression test runs are required (and they will be) you will save more time in the long run • Can be useful as a last resort when maintaining badly designed software with no test suite
  • 87. 87 Testing with a Debugger Procedure – Start the program and breakpoint the method requiring test – Exercise a program feature that will trigger a call to the method – Change the input parameters and object state in the debugger as appropriate to set up the test pre-state – Either step through the code or breakpoint the end of the method and examine the post-state against expected criterion – You should document the tests done so that they can be repeated if necessary (as a checklist)
  • 88. 88 Types of Test Coverage • Types of test coverage, in order of difficulty and completeness – Statement (or segment) coverage – Branch Coverage – Branch Condition Coverage – Multiple-Condition Coverage – Path Coverage – Exhaustive coverage (rarely possible)
  • 89. 89 Test Coverage How much coverage is enough? • “It compiled!” • “I ran through it a couple of times and it seemed to work okay.” • “I ran 64 test cases and achieved 100% statement and 77% branch coverage.”
  • 90. 90 Test Coverage • IEEE 1008 requires a minimum 100% statement coverage (as does IBM’s corporate standard) – statement coverage alone is not considered a good criterion of test coverage • A high branch coverage in addition to statement coverage is a better indication of good test coverage (but may be difficult to achieve)
  • 91. 91 Test Coverage - Case Study Percent Coverage System Under Test Segment Branch TeX 85 72 AWK 70 59 • Test coverage achieved by functional test suites for AWK and TeX Source: Handbook of software reliability engineering, Horgan, 1996
  • 92. 92 Getting High Test Coverage • High test coverage is difficult when code depends on the results of external modules. – replace external modules with stubs – stubs are designed to return values which will exercise different paths of the code – Discussion: what approaches could be used to test the error handling in the following fragment of C? mem = (char *) malloc(MEMSIZE); if (mem != null) { /* do something with mem */ } else { /* error handling */ }
  • 93. 93 Test Coverage - a Final Note • Sometimes it seems that getting 100% statement coverage is impossible. There may be good reasons: – tests are run with debugging code compiled into the executable, but the debugging code is switched off (i.e protected by conditionals) – some of the code is dead and can never be executed. • When maintenance is done on a program and old code is left hanging around because “somebody might need it”, this is known as “Lava Flow”. • With proper Configuration Management, there is no excuse for leaving dead code around; test coverage analysis can help to find dead code.
  • 94. 94 Code Coverage Tools • Instrument the code during compile • When the code is run it collects coverage data • Assess coverage to determine where to extend tests • See http://c2.com/cgi/wiki?CodeCoverageTools
  • 95. 95 http://c2.com/cgi/wiki?CodeC overageTools for Java • EMMA @ http://emma.sourceforge.net/ • Hansel @ http://hansel.sourceforge.net/ • jcoverage @ http://www.jcoverage.com/ • Clover @ http://www.thecortex.net/clover/ • GroboUtils @ http://groboutils.sourceforge.net • NoUnit? @ http://nounit.sourceforge.net/ • Quilt @ http://quilt.sourceforge.net/ • Gretel @ http://sourceforge.net/projects/gretel • The "Java Test Coverage Tool" @ http://www.semanticdesigns.com/Products/TestC overage/JavaTestCoverage.html • MutationTesting: (which isn't really CodeCoverage, but it's related) • JesTer @ http://jester.sourceforge.net/ for .NET: • NCover @ http://ncover.sourceforge.net/ • CoverageEye?.NET @ http://www.gotdotnet.com/Community/UserSamples/Deta ils.aspx?SampleGuid=881a36c6-6f45-4485-a94e- 060130687151 • The "C# Test Coverage Tool" @ http://www.semanticdesigns.com/Products/TestCoverage /CSharpTestCoverage.html • "DevPartner? Studio Professional Edition" @ http://www.compuware.com/products/devpartner/1563_E NG_HTML.htm • "Perform Code Coverage Analysis with .NET to Ensure Thorough Application Testing", an MSDN article on building "A custom code coverage tool" @ http://msdn.microsoft.com/msdnmag/issues/04/04/CodeC overageAnalysis/default.aspx C/C++: • tcov = Sun Unix C profiler. See "tcov(1)" man page. It annotates (mangles) your source code to add instrumentation. • gcov = GNU C/C++ equivilent of "tcov". • Dynamic Code Coverage for Sun Solaris @ http://www.dynamic-memory.com/coverageanalysis.php
  • 96. 96 Test Coverage • Compilation setup • Logging tests • Results
  • 98. 98 Test Coverage Tools Tool Statement Branch Multiple- Condition Decision Path Rational Pure Coverage     TestWell CTC++     McCabe Tools    
  • 99. 99 Memory Bugs • Common memory use bugs – memory allocated in constructors is not de-allocated in corresponding destructors (or anywhere else) – indexed memory reads and writes go out of bounds – memory is not initialised before use – memory is not accessed after de-allocation • Rational Purify detects all of these things (plus others) • GPL or free libraries exist that detect these bugs by replacing memory management routines – search for “memory leak” on www.freshmeat.net – are usually specific to UNIX/Linux and GCC
  • 100. 100 Memory Leak Detection • Instrument the code during compile • When the code is run it collects memory allocation data • When the code closes it looks for leaked memory
  • 101. 101 Memory Leak Detection • Compile • Run • Find error
  • 102. 102 Purify • Leak detection finds memory leaks which consume more memory
  • 103. 103 Performance Bugs • Module testing should aim to identify and eliminate bottlenecks – without a performance analysis tool, optimisation efforts are nearly always wasted efforts • The following tools can highlight performance problems: – gprof (free on Linux) – Rational Quantify for UNIX and NT
  • 104. 104 Performance Measurement • A performance analysis tool may have some or all of the following features: – time spent in a function or method – time spent in a program segment – contributing time of called functions • Times may be specified as % of total, clock cycles or wall time
  • 105. 105 Quest JProbe • Analyse call hierarchy of Java applications
  • 106. 106 Overview  White-Box Test Design  Unit Test Automation  Unit/Integration Test Issues – Harnesses & Stubs
  • 107. 107 Overview  White-Box Test Design  Unit Test Automation  Unit/Integration Test Issues – Module / Unit Testing – Integration Levels – Integration Testing – Harnesses & Stubs – Test Oracles – Object-Orientation Concerns – Coding Standards
  • 108. 108 Module (Unit) Testing • Module Testing is applied at the level of each module of the system under test. • Module testing is nearly always done by the developers themselves, before the module is handed over for integration with other modules. • Usually the testing at this level is structural (white- box) testing. • Module Testing is sometimes called Unit Testing representing the lowest level item available for testing.
  • 109. 109 Module Testing Questions • Has the component interface been fully tested? • Have local data structured been exercised at their boundaries? • Have all independent basis paths been tested? • Have all loops been tested appropriately? • Have data flow paths been tested? • Have all error handling paths been tested?
  • 110. 110 White Box Module Testing The goal is to extensively test the code with a view to exposing and fixing bugs prior to integration with other’s work. • Finds lurking bugs that are very hard to find cost- effectively during integration or functional testing • Tools are essential to get test coverage data • REMEMBER: Caution is required – you must have a specification against which to test – without a spec, you are simply testing that the code does what you think it does (but is it doing the RIGHT thing?)
  • 111. 111 Module Test Technique • The module under test is usually treated as a white box; however a “grey” box is more appropriate: 1. Systematic test design techniques are applied to the specification of the module 2. The module is tested 3. If any tests fail the module is debugged and the process is repeated from step 2 4. Test coverage is evaluated: if coverage criteria is met then the module is considered verified; otherwise the process is repeated from step 1 • knowledge of the algorithms in use can help find new test cases when coverage is too low
  • 112. 112 Module Test Approaches • Ad-hoc • Checklist • Automated • Planned
  • 113. 113 Adhoc Approach Usually the task of the implementing developer • Ad-hoc approach: random testing before the modules are handed over for integration Pros – quick (sometimes very quick) Cons – Difficult to quantify how well the code was tested before integration – Bugs slip through to later testing where they are much more difficult (and costly) to find and fix – Less likely that the developer will design testable code
  • 114. 114 Checklist Approach A module test checklist is the set of abbreviated test cases used by a developer to ensure thorough testing of their module. – Called a checklist because it usually lists inputs and expected results and has a checkbox to indicate the result of executing the test – may not be applicable if tests are automated; although the automated test may have its origins in a test checklist
  • 115. 115 Checklist Approach Checklists are more suitable for developer testing than standard test plans because: – they minimise the amount of work required of a developer to prepare a repeatable set of test cases – a developer does not require detailed test instructions because they already know how to apply a test to their own code – YOU try getting a developer to write an IEEE 829 compliant test plan!
  • 116. 116 Example Test Checklists Module Specific class IntSet { ... void add(int i); // contains(i) => exception; otherwise adds i void remove(int i); // !contains(i) => exception; otherwise removes i bool contains(int i); // returns true iff i is contained in the set ... } ID Test Case Check S1 contains(x) fails for all values of x when empty set is constructed S2 add value 1 to empty set succeeds S3 add value 1 to set containing 1 (post S2) throws exception etc…
  • 117. 117 Example Test Checklists Generic 1 Myers 1979 1. Is the number of input parameters equal to number of arguments? 2. Do parameter and argument attributes match? 3. Do parameter and argument units system match? 4. Is the number of arguments transmitted to called modules equal to number of parameters? 5. Are the attributes of arguments transmitted to called modules equal to attributes of parameters? 6. Is the units system of arguments transmitted to called modules equal to units system of parameters? 7. Are the number of attributes and the order of arguments to built-in functions correct? 8. Are any references to parameters not associated with current point of entry? 9. Have input only arguments altered? 10. Are global variable definitions consistent across modules? 11. Are constraints passed as arguments? 12. When a module performs external I/O, additional interface tests must be conducted.
  • 118. 118 Example Test Checklists Generic 2 General 1 Does input data vary, including maximum, minimum, and nominal values? (All alike data, especially all zeroes, is usually a poor choice.) 2 Is erroneous input data used? (All error conditions should be checked.) 3 Do the tests demonstrate that the code completely satisfies each requirement? 4 Does the actual output match the expected output? Data-Declaration Error Testing 5 Have all the data structures been explicitly tested? 6 Has all data been properly initialized? (e.g., initialized with the correct data type, default values) 7 Have all global data structures been tested? Data Referencing Errors 8 Are all variables set to the proper value or initialized correctly?
  • 119. 119 Automated Approach Tests are automated through building harnesses and stubs Pros • Tests can be repeated quickly and efficiently as minor changes are made during development • No need to select specific test cases to save time during regression testing Cons • has high up front cost, and may be costly to maintain if the test code is badly designed • automation is difficult when testing a system with spaghetti dependencies
  • 120. 120 Planned Approach • Developer plans to test systematically from the beginning. • The plan may involve testing incrementally as classes are constructed, or to do testing once most or all of the classes are complete • When complete, release the module and its test code for integration with the system
  • 121. 121 Planned Approach Pros – tests are documented and can be reviewed and reproduced – automated tests reduce the expense of regression tests – a systematic approach means many more bugs are found early in the development process where they are least expensive to fix Cons – Amount of test code (i.e. test harness and stubs) often outweighs the “real” module code (i.e. lots more work) – Changes to released software will usually require updates to the test-suite
  • 122. 122 Planned Approach Test planning happens during the module’s design and implementation – design for testability – a “checklist” of things to test is collated during design and implementation • a peer or team leader may review the checklist for suitability and suggest other things to test – ideally module tests are automated • reduce duplication by specifying test cases directly in code • important to ensure that the purpose of each test case is documented
  • 123. 123 Overview  White-Box Test Design  Unit Test Automation  Unit/Integration Test Issues – Harnesses & Stubs
  • 124. 124 Test Harnesses • Supporting code and data used to provide an environment for testing components of your system. – Typically used during unit/module test – Typically created by the developer of the code – vary between simple user interfaces to allow tests to be conducted manually, through to fully automated execution of tests to provide repeatability when the code is modified. • Building test harnesses may account for 50% of the total code produced – valuable asset, and should be controlled in the same way the code is managed
  • 125. 125 Test Automation Techniques • code driven – test cases are embedded directly in the source code of the test harness – simple to get tests up and running – requires little effort for small unchanging modules – is not easily maintainable for large modules, or modules were tests are likely to be added a change frequently
  • 126. 126 Test Automation Techniques • data driven – the test harness does not contain any test cases; instead it reads data from a file that defines the inputs and expected outputs of each test case – higher initial overhead in design of interpreter and data file formats – initial overhead is quickly recouped by the ease in adding new tests
  • 127. 127 Data Driven Test Harness The test harness usually conforms to the following structure: while data file is not empty read inputs and outputs from data file call function with inputs if results of function match expected outputs register TC passed else register TC failed end if end while output summary
  • 128. 128 Example - Harness /* Calculate the hypotenuse of a right angle */ /* triangle . nOpposite and nAdjacent must values */ /* be non negative . Return the hypotenuse or –1 */ /* for invalid input */ double calcHypotenuse ( double nOpposite, double nAdjacent ) { if ( nOpposite < 0 or nAdjacent < 0 ) { return –1; } return ( sqrt(pow(nOpposite,2)+ pow(nAdjacent,2)) ); } /* Test Harness – this does all the work */ main(…) { int count = 0; // count the no of tests executed int fail = 0; double result; … /* open the input script */ … while ( line = readLine(inputFile) != EOF ) { if ( is_comment(line) ) { continue; } count++; /* split line into testid,opposite,adjacent,expected */ … result = calcHypotenuse ( opposite, adjacent ); if ( result != expected ) { fail++; output(“Test failed: %s( %d, %d ) got %d expected %dn”, testid, opposite, adjacent, result, expected ); } } /* output the final stats */ output(“Tests run: %dn”, count); output(“Tests OK: %dn”, count-fail); output(“Tests failed: %dn”, fail); }
  • 129. 129 Example - Harness Run • Sample Input Data • Sample Output # format: testid,opposite,adjacent,expected Test1,3,4,5 Test2,3,4,6 # just to try and force a failure Test3,-3,4,-1 Test4,4,-1,-1 Test5,0,4,4 Test failed: Test2( 3, 4 ) got 5 expected 6 Tests run: 5 Tests OK: 4 Tests failed: 1
  • 130. 130 Test Stubs • dummy components that stand in for unfinished components during unit/module testing and integration testing. – quite often code routines that have no or limited internal processing • may always return a specific value • request value from user • read value from test data file • simulators may be used as test stubs to mimic other interfaced systems
  • 131. 131 Test Stubs • Sometimes code for a low level module is modified to provide specific control – E.g. a file I/O driver module may be modified to inject file I/O errors at specific times, and thus enable the error handing of I/O errors to be analysed
  • 132. 132 Example - Stub • Same result for each call enum Method { GET, POST }; struct response { int code; String content; String header; }; /* static stub – commonly used since predictable results */ response sendHttpRequest( String url, Method getpost, String params) { response res; res.code = 200; /* status OK */ res.content = “<html><title>Hello</title><body>testing</body></html>”; res.header = “”; return res; }
  • 133. 133 Example - Stub • Lookup result from predefined lookup table or file /* get value from global lookup table – generated from input script */ response sendHttpRequest( String url, Method getpost, String params) { response res; /* assume test input script included data to populate lookup table */ res = lookup(url); return res; }
  • 134. 134 Example - Stub • Conditional response (if file accessible) /* get value from a file */ response sendHttpRequest( String url, Method getpost, String params) { response res; /* assume a file has been opened and filehandle is accessible */ if ( code = readLine(filehandle) ) { res.code = code; } else { res.code = 400; /* fail */ } if ( content = readLine(filehandle) ) { res.content = content; } if ( header = readLine(filehandle) ) { res.header = header; } return res; }
  • 135. 135 Example - Stub • Error injection using actual method • Uses mode (controlled by harness) to determine whether to inject error /* get value from a file */ response sendHttpRequest( String url, Method getpost, String params) { response res; /* assume a file has been opened and filehandle is accessible */ if ( mode = normal ) { res = actual_sendHttpRequest(url, getpost, params) } else { res.code = 400; /* fail */ } return res; }
  • 136. 136 Coordinating Harnesses and Stubs TC01:3,4,1998;30;T # normal date TC02:29,2,1999;28;F # not a leap year TC03:29,2,2000;29;T # leap year TC04:29,2,2100;28;F # not a leap year The data file may have fields indicating data that should be returned by stubbed functions during the test. The stubbed functions return global variables that are set by the test harness after reading the appropriate value from the test file. For example, the daysInMonth function used by checkDate is stubbed. It returns a pre- determined value from the test harness data file (shown in bold). bool checkDate(int d, int m, int y) { if ( y <= 0 ) return false; if ( m < 1 || m > 12 ) return false; if ( d < 1 || d > daysInMonth(m, isLeapYear(y)) ) return false; return true; }
  • 137. 137 Coordinating Harnesses and Stubs (cont) TC01:3,4,1998;30;T # normal date TC02:29,2,1999;28;F # not a leap year TC03:29,2,2000;29;T # leap year TC04:29,2,2100;28;F # not a leap year int daysInMonth (int month, bool leapYear) { return globalDaysInMonth; } int isLeapYear(int y) { return true; } /* simple stub */ while (data remaining in file) { read data line into (TCID, (d, m, y), globalDaysInMonth, Expected) if (checkDate(d,m,y) == Expected) { register (TCID,pass) else register (TCID,fail) } bool checkDate(int d, int m, int y) { if ( y <= 0 ) return false; if ( m < 1 || m > 12 ) return false; if ( d < 1 || d > daysInMonth(m, isLeapYear(y)) ) return false; return true; }
  • 138. 138 Mock Objects • “Take the place of real objects for testing functionality that interacts with and is dependent on the real objects” Test Driven Development, A Practical Guide, David Astels, Prentice Hall, 2003
  • 139. 139 Mock Object Example From Test Driven Development, A Practical Guide, David Astels, Prentice Hall, 2003 • Takes Die object • Random behaviour • Difficult to test with real object public class Player { Die myD20 = null; public Player(Die d20) { myD20 = d20; } public boolean attack(Orc anOrc) { if (myD20.roll() > = 13) { return hit(anOrc); } else { return miss(); } } private boolean hit(Orc anOrc) { anOrc.injure(myD20.roll()); return true; } private boolean miss() { return false; } }
  • 140. 140 Create Mock Interface • Extract an interface from Die public interface Rollable { int roll() } public class Die implements Rollable { // … } public class Player { Rollable myD20 = null; public Player(Rollable d20) { myD20 = d20; } //… }
  • 141. 141 Create Tests With Mock • MockDie that always rolls a certain value is created • Test is created with a MockDie that rolls 10 • Initialise Player with this MockDie • Check outcomes with MockDie public class MockDie implements Rollable { private int returnValue; public MockDie(int constantReturnValue) { returnValue = constantReturnValue; } public int roll() { return returnValue; } } public void testMiss() { Rollable d20 = new MockDie(10); Player badFighter = new Player(d20); Orc anOrc = new Orc(); assertFalse(“Attack should have missed.”, badFighter.attack(anOrc)); }
  • 142. 142 Uses of Mock Objects (and stubs in general) • To help keep design decoupled • To check your code’s usage of another object • To test drive your code from the inside out • To make your code run faster • To make your code easier to develop code that interacts with hardware devices, remote systems, and other problematic resources • To defer having to implement a class • To let us test-drive components in isolation from the rest of the system • To promote interface-based design • To promote composition over inheritance • To refine interfaces • To test unusual, unlikely and exceptional situations Test Driven Development, A Practical Guide, David Astels, Prentice Hall, 2003