Software Engineering Requirements Engineering

Download Report

Transcript Software Engineering Requirements Engineering

Unit Testing with JUnit
CS 3331
Fall 2009
Kent Beck and Eric Gamma. Test Infected: Programmers Love
Writing Tests, Java Report, 3(7):37-50, 1998.
Available from: http://junit.sourceforge.net/doc/testinfected/testing.htm
1
Unit Testing




Introduction
Conventional approach
Unit testing with JUnit
More on JUnit
2
Testing in General

Testing


A way of showing the correctness of software
Phases



Unit testing
 To test each module (unit, or component)
independently
 Mostly done by developers of the modules
Integration and system testing
 To test the system as a whole
 Often done by separate testing or QA team
Acceptance testing
 To validate system functions for (and by)
customers or user
3
What Is Unit Testing?

Definition


Testing is the process of showing that a
program works for certain inputs.
A unit is a module or a small set of modules.
In Java, a unit is a class or interface, or a set of
them, e.g.,
 An interface and 3 classes that implement it, or
 A public class along with its helper classes.


Unit testing is testing of a unit.
4
Question

Do you get more confidence by running
more test data?
5
Why Unit Testing?


Code isn’t right if it’s not tested.
Practical



Most programmers rely on testing, e.g.,
Microsoft has 1 tester per developer.
You could get work as a tester.
Divide-and-conquer approach




Split system into units.
Debug unit individually.
Narrow down places where bugs can be.
Don’t want to chase down bugs in other units.
6
Why Unit Testing? (Cont.)

Support regression testing


So can make changes to lots of code and
know if you broke something.
Can make big changes with confidence.
7
How to Do Unit Testing

Build systems in layers



Starts with classes that don’t depend on
others.
Continue testing building on already tested
classes.
Benefits


Avoid having to write (test) stubs.
When testing a module, ones it depends on
are reliable.
8
Question


How does low coupling help testing?
How does high coupling hurt it?
9
Program to Test
public final class IMath {
/**
* Returns an integer approximation to the square root of x.
*/
public static int isqrt(int x) {
int guess = 1;
while (guess * guess < x) {
guess++;
}
return guess;
}
}
10
Conventional Testing
/** A class to test the class IMath. */
public class IMathTestNoJUnit {
/** Runs the tests. */
public static void main(String[] args) {
printTestResult(0);
printTestResult(1);
printTestResult(2);
printTestResult(3);
printTestResult(4);
printTestResult(7);
printTestResult(9);
printTestResult(100);
}
private static void printTestResult(int arg) {
System.out.print(“isqrt(“ + arg + “) ==> “);
System.out.println(IMath.isqrt(arg));
}
}
11
Conventional Test Output
Isqrt(0) ==> 1
Isqrt(1) ==> 1
Isqrt(2) ==> 2
Isqrt(3) ==> 2
Isqrt(4) ==> 2
Isqrt(7) ==> 3
Isqrt(9) ==> 3
Isqrt(100) ==> 10


What does this say about the code? Is it right?
What’s the problem with this kind of test output?
12
Solution?

Automatic verification by testing program



Can write such a test program by yourself, or
Use a testing tool such as JUnit.
JUnit



A simple, flexible, easy-to-use, open-source, and
practical unit testing framework for Java.
Can deal with a large and extensive set of test cases.
Refer to www.junit.org.
13
Testing with JUnit
import junit.framework.*;
/** A JUnit test class to test the class IMath. */
public class IMathTest extends TestCase {
/** Tests isqrt. */
public void testIsqrt() {
assertEquals(0, IMath.isqrt(0)); // line 23
assertEquals(1, IMath.isqrt(1));
assertEquals(1, IMath.isqrt(2));
assertEquals(1, IMath.isqrt(3));
assertEquals(2, IMath.isqrt(4));
assertEquals(2, IMath.isqrt(7));
assertEquals(3, IMath.isqrt(9));
assertEquals(10, IMath.isqrt(100));
}
14
Testing with JUnit (Cont.)
/** Returns the test suite for this test class. */
public static Test suite() {
return new TestSuite(IMathTest.class);
}
/** Run the tests. */
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
// junit.swingui.TestRunner.run(suite());
}
}
15
Compilation and Output
$ javac IMath.java IMathTest.java
$ java IMathTest
.F
Time: 0.02
There was 1 failure:
1) testIsqrt(IMathTest)junit.framework.AssertionFailedError: expected:<0> but
was:<1>
at IMathTest.testIsqrt(IMathTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMeth...
at sun.reflect.Delegating...
at IMathTest.main(IMathTest.java:17)
FAILURES!!!
Tests run: 1, Failures: 1, Errors: 0
Question: Is this better? Why?
16
Exercise

Write a JUnit test class for testing
public class ForYou {
/** Return the minimum of x and y. */
public static int min(int x, int y) { ... }
}
17
Exercise (Cont.)
By filling in the following:
public class ForYou {
/** Return the minimum of x and y. */
public static int min(int x, int y) { ... }
}
import junit.framework.*;
/** Test ForYou. */
public class ForYouTest extends TestCase {
/** Test min. */
public void testMin() {
}
// the rest as before …
}
18
Some Terminology

Definition




A test data (or case) for a method M is a pair of (o,
args), where
 o is not null and M can be sent to o,
 args is a tuple of arguments that can be passed to M.
A test data, (o, args), for M succeeds iff o.M(args)
behaves as expected.
A test data, (o, args), for M fails iff it does not behave
as expected.
Question


Why should o not be null?
If M has a bug that is revealed by a test data, does
that test data for M succeeds or fails?
19
Parts of Test Code

Definition




The test fixture is the set of variables used in testing.
The test driver is the class that runs the tests.
The test oracle for a test data is the code that decides
success or failure for that test data.
Question


What in the code we saw so far was the test driver,
and the oracle?
What difference is there between JUnit testing and
non-JUnit testing in what we saw before?
20
Basic Usage of JUnit
To test a type T:
1. Write a class like:
import junit.framework.*;
/** A JUnit test class for the class T. */
public class TTest extends TestCase {
/** Runs the tests. */
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
/** Returns the test suite for this test class. */
public static Test suite() {
return new TestSuite(TTest.class);
}
<test methods go here>
}
21
Basic Usage of JUnit (Cont.)
2. Compile T.java and TTest.java
$ javac T.java TTest.java
3. Run the JUnit graphical user interface on TTest
$ java junit.swingui.TestRunner TTest
or
Run the text interface (good from makefiles)
$ java TTest
4. Look at the failures and errors
22
Naming Convention


Test methods start with “test”
e.g., testIsqrt, testMin
Test classes end with “Test”
e.g., IMathTest, ForYouTest
23
Assertion Methods
Method
Description
assertEquals(a,b)
assertFalse(a)
assertNotSame(a, b)
Test if a is equal to b
Test if a is false
Test if a and b do not refer to the
identical object
Test if a is null
Test if a and b refer to the identical
object
Test if a is true
assertNull(a)
assertSame(a,b)
assertTrue(a)
- Static methods defined in junit.framework.Assert
- Variations taking string error messages
24
More on JUnit -- Test Fixture

Sharing test data among test methods
public class TTest extends TestCase {
// other methods here …
protected void setUp() throws Exception {
// initialize test fixture variables.
}
protected void tearDown() throws Exception {
// uninitialize test fixture variables.
}
// test fixture variables, i.e., fields shared by several test methods.
}
25
Example
public class PointTest extends TestCase {
private Point p; // test fixture variable
protected void setUp() { // initializes text fixture variables
p = new Point(10, 10);
}
protected void tearDown() { } // clean up text fixture variables
public void testSetX() { // tests SetX
p.setX(20);
assertEquals(20, p.getX());
}
public void testSetY() { // tests SetY
p.setY(30);
assertEquals(30, p.getY());
}
// template and other test methods here…
}
26
More on JUnit -- Test Suite

Definition


A test suite is a set of test methods and other
test suites.
Test Suite


Organize tests into a larger test set.
Help with automation of testing.
27
Example
public class AllTestSuite extends TestCase {
/** Returns the test suite for this test class. */
public static Test suite() {
TestSuite suite = new TestSuite() {
public String toString() {
return "Test suite for Project T";
}
};
suite.addTestSuite(T1Test.class);
suite.addTestSuite(T2Test.class);
…
suite.addTestSuite(TnTest.class);
return suite;
}
// the rest of methods as before …
}
28
More on JUnit?


Refer to www.junit.org
JUnit APIs available from the course Web
page
29