Beruflich Dokumente
Kultur Dokumente
Lecture 5 & 6:
Unit testing & debugging
2013
Outline
What is testing?
Test (stand-alone) procedures:
Defensive programming
Debugging
2013
What is testing?
A form of program validation
Validation means to validate our belief that a
program functions correctly:
2013
Testing method
Test incrementally
Three techniques:
2013
Test case
Exhaustive testing is impractical
Goal: find a small, representative set of test
cases
Test case is a set of input data values of a
given test unit
Belief: succeeds with TCs succeeds with all
input
2013
Test case
Input domains
int
Test cases
int[]
2013
someMethod(int x, int[] a)
2013
use JUnit
2a
2013
Generate TDSs
Generate TDSs
Generate TDSs
int
someMethod(int x, int[] a)
x1
x2
TDS
int[]
a1
a5
a4
2013
a2
a3
Combine TDSs
Generate TDSs
int
Combine TDSs
someMethod(int x, int[] a)
x1
<x1,a1>
x2
<x2,a1>
...
int[]
<x1,a5>
<x2,a5>
a1
a5
a4
2013
a2
a3
10
Test cases
Generate TDSs
int
Combine TDSs
Test cases
someMethod(int x, int[] a)
x1
<x1,a1>
x2
<x2,a1>
...
int[]
<x1,a5>
<x2,a5>
a1
a5
a4
2013
a2
a3
11
Generate TDSs
TDS is a sub-set of values of an input domain
One input domain may contain several TDSs
Steps to generate TDSs:
2013
12
Techniques
Two techniques:
2013
13
?
14
2013
15
isPrime
/**
* @effects
*
if p is a prime
*
returns true
*
else
*
returns false
*/
public static boolean isPrime(int p)
2013
16
output conditions
exceptional conditions
2013
17
search
/**
* @effects
*
if a is null
*
throws NullPointerException
*
else if x is in a
*
returns i such that a[i] = x
*
else
*
throws NotFoundException
*/
public static int search(int[] a, int x)
Ranges:
2013
x: {y | y in a} + {y | y not in a}
FIT330 Software Engineering
18
sqrt
/**
* @requires
* @effects
*
*/
public static
Ranges:
2013
x: [0,+INF)
epsilon: (.00001, .001)
19
isPrime
/**
* @effects
*
if p is a prime
*
returns true
*
else
*
returns false
*/
public static boolean isPrime(int p)
Ranges:
2013
primes: {1,2,3,5,...}
non-primes: {4,6,8,9,...}
20
2013
iterator
data abstraction
type hierarchy
21
2013
atypical:
22
x: {y | y in a} + {y | y not in a}
TDS(s):
2013
x: {1,2}
23
sqrt
Ranges:
x: [0,+INF)
TDS(s):
2013
y?
24
isPrime
Ranges:
primes: {2,3,5,...}
non-primes: {4,6,8,9,...}
TDS(s):
2013
primes: {2,3,5,31,65537}
non-primes: {4,32,65538}
y?
25
ease TC generation
Disadvantages:
2013
26
2013
27
conditional
loop
recursion
Criteria:
2013
conditional expression
28
Conditional
if P(x)
// do
else if
// do
else
// do
this
Q(x)
that
somethingelse
Range(s):
2013
29
Example: conditional
static int maxOfThree(int x,int y,int z) {
if (x > y) {
if (x > z) return x; else return z;
} else { // x <= y
if (y > z) return y; else return z;
}
}
2013
x > y,z
zx>y
x,z y
x y z
y?
30
deterministic loop
static int someMethod(int n) {
for (int i = 1; i <= n; i++) {
// do something
}
}
Range(s) for n:
2013
(-INF,0]
[1,+INF]
31
non-deterministic loop
static int someMethod(int x) {
while (x > 0) {
// do something with x
}
}
Range(s) for x:
2013
(-INF,0]
[1,+INF)
y?
32
recursion
static int fact(int n) {
if (n < 1)
return -1;
else if (n == 1)
return 1;
else
return n * fact(n-1);
}
Range(s) for n:
2013
(-INF,1)
{1}
(1,+INT)
y?
FIT330 Software Engineering
33
loop: 0, 1, 2
recursion: 0, 1 (base), 2 (inductive once), 3
(inductive twice)
Termination:
2013
termination values
34
2013
x > y,z
zx>y
{ (3,2,4), (3,2,3) }
x,z y
x y z
35
deterministic loop
static int someMethod(int n) {
for (int i = 1; i <= n; i++) {
// do something
}
}
Range(s) for n:
2013
(-INF,0]
[1,+INF]
TDS(s) for n:
{0,1,2}
36
non-deterministic loop
static int someMethod(int x) {
while (x > 0) {
// do something
}
}
Range(s) for x:
2013
(-INF,0]
[1,+INF)
TDS(s) for x:
{0,1,2}
y?
37
recursion
static int fact(int n) {
if (n < 1)
return -1;
else if (n == 1)
return 1;
else
return n * fact(n-1);
}
Range(s) for n:
2013
(-INF,1)
{1}
(1,+INT)
TDS(s) for n:
{-1, 1, 2, 3}
y?
38
y?
39
2013
40
n = 2
i = {1,2}
m++;
}
}
2013
41
Disadvantages:
2013
42
2b
2013
using JUnit
43
General approach
Develop test drivers to:
2013
44
Test driver
A small program
Specified as a data abstraction
Tasks include:
45
@Test
+ squareRoot()
2013
Num
46
IntSet
- elements: Vector
+ IntSet()
+ insert(int)
+ remove(int)
+ isIn(int): boolean
+ size(): int
+ elements(): Iterator
+ repOK(): boolean
+ toString(): String
47
2013
48
Assertion
A boolean statement validated automatically by
the run-time environment
Java keyword: assert
Usage:
2013
49
Assertion example
IntSet s = ... // initialise s
assert (s.repOK() == true);
50
Test method:
throws AssertionError
2013
51
Example: SquareRootTest
ch10.junit4.SquareRootTest
Note:
SquareRootTest
2013
52
Specification
/**
* @overview A test driver for the Num.sqrt method
*/
public class SquareRootTest {
/**
* @modifies System.out
* @effects
*
for each test case tc = < x,e,r >
y?
*
if |Num.sqrt(x)^2 - r^2| > e
*
throws AssertionError
*
else
*
displays Num.sqrt(x) on the std output
*
*/
@Test
public void squareRoot() throws AssertionError
}2013
FIT330 Software Engineering
53
Implementation
@Test //(timeout = 5000)
public void squareRoot() throws AssertionError {
//... (code omitted) ...
// test cases
float[] tcEps = { 0.00002f, 0.0001f, 0.009f };
float[] tcX = { 0f, 0.001f, 0.01f, 0.09f, 0.5f,
1f, 2f, 10f, 100f,
2147483600f };
// test results
float[] results = new float[tcX.length];
for (int i = 0; i < tcX.length; i++){
results[i] = (float) Math.sqrt(tcX[i]);
};
2013
54
float x,e,r;
for (int i = 0; i < tcX.length; i++) {
x = tcX[i];
r = results[i];
for (int j = 0; j < tcEps.length; j++) {
System.out.println(">>Test case " +
((i*tcEps.length)+j));
e = tcEps[j];
float result = Num.sqrt(x, e);
// assume same delta error b/w two results
assertEquals(r * r, result * result, 2 * e);
System.out.printf("sqrt(%f,%f) = %f " +
"(expected = %f) %n", x, e, result, r);
}
}
} // end squareRoot
2013
55
DEMO
ch10.junit4.SquareRootTest
2013
56
static
57
DEMO
Example
ch10.junit4.
SquareRootParameterisedTest
2013
58
Defensive programming
Being extra careful when programming
Three additional 'checks':
2013
59
implements repOK
Check @requires:
2013
60
Example
String s = Comm.receive();
if (s.equals("deliver")) {
// carry out the deliver request
} else if (s.equals("examine")) {
// carry out the examine request
}
2013
61
Example: defensive
String s = Comm.receive();
if (s.equals("deliver")) {
// carry out the deliver request
} else if (s.equals("examine")) {
// carry out the examine request
} else {
// handle error case
}
2013
62
Use assertion
String s = Comm.receive();
if (s.equals("deliver")) {
// carry out the deliver request
} else if (s.equals("examine")) {
// carry out the examine request
} else {
// this can never happen
assert false;
}
2013
63
Enable/disable assertions
Assertions are disabled by default
To enable (disable) use JVM's option -ea (da)
To enable assertions:
java -ea MyProgram
To disable assertions:
java -da MyProgram
2013
64
2013
code quality
cost/time
performance
65
Debugging
To uncover and correct bugs (errors)
Examine the intermediate states
Need test cases that produce the bugs
Efficiency depends on:
2013
design
implementation
66
Debugging steps
Find bug-producing TCs
Locate buggy code regions
Fix buggy code regions
Retest program (regression testing)
2013
67
Test program
Debug
flow-chart
buggy?
Y
Debugging
End test
2013
68
2013
69
refuted?
N
Generate bug-producing
TCs
2013
70
2013
71
2013
72
2013
73
Use a
debugger
Examine intermediate results
code
region
found?
Y
2013
74
DEMO
Debug
ch10.Num.search
2013
75
2013
76
77
2013
78
Summary
Testing is a practical method of validating a program's
correctness
Test cases are generated from specification (BBT)
and/or code (GBT)
Test drivers are data abstractions implemented using
JUnit
Defensive programming involves inserting checks to
detect errors
Debugging is a method to uncover bugs and correct the
affected code regions
2013
79
Questions?
2013
80