You are on page 1of 29

Unit Testing with JUnit

CS 3331
Fall 2007

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
 Startswith 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:
6) 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) Test if a is equal to b
assertFalse(a) Test if a is false
assertNotSame(a, b) Test if a and b do not refer to the
identical object
assertNull(a) Test if a is null
assertSame(a,b) Test if a and b refer to the identical
object
assertTrue(a) Test if a is true

- 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

You might also like