Unit Testing
Download
Report
Transcript Unit Testing
Unit Testing with JUnit
CS 3331
JUnit website at http://www.junit.org
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
Introduction
Testing
A process of showing that a program works for certain
inputs
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?
Testing focusing on the smallest units of code,
such as
Component tested in isolation from the rest of the
system and in a controlled environment:
Functions, procedures, subroutines, subprograms
Methods, classes
Uses appropriately chosen input data
Uses component-level design description as guide
Unit testing is testing of a unit.
Often the target of testing frameworks such as
JUnit
4
Unit in Java?
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
A public class along with its helper classes.
5
Question
Do you get more confidence by running
more test data?
6
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.
7
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.
8
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.
9
Question
How does low coupling help testing?
How does high coupling hurt it?
10
Program to Test
public 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;
}
}
11
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));
}
}
12
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?
13
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
14
Testing with JUnit
import org.junit.Test;
import static org.junit.Assert.*;
/** A JUnit test class to test the class IMath. */
public class IMathTest {
/** Test isqrt. */
@Test
public void testIsqrt() {
assertEquals(0, IMath.isqrt(0)); // line 13
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));
}
15
Testing with JUnit (Cont.)
/** Run the tests. */
public static void main(String[] args) {
org.junit.runner.JUnitCore.main("IMathTest");
}
}
16
Compilation and Output
$ javac IMath.java IMathTest.java
$ java IMathTest
JUnit version 4.10
.E
Time: 0.015
There was 1 failure:
1) testIsqrt(IMathTest)
java.lang.AssertionError: expected:<0> but was:<1>
at org.junit.Assert.fail(Assert.java:93)
…
at IMathTest.main(IMathTest.java:13)
FAILURES!!!
Tests run: 1, Failures: 1
Question: Is this better? If so, why?
17
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) { ... }
}
18
Exercise (Cont.)
public class ForYouTest {
/** Test min. */
@Test
public void testMin() {
}
// the rest as before …
}
public class ForYou {
/** Return the minimum of x and y. */
public static int min(int x, int y) { ... }
}
In Eclipse,
- Select a source code folder
- Right click (pop-up menu)
- Select New > Other… >
JUnit > Junit Test Case
19
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?
20
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?
21
Basic Usage of JUnit
To test a type T:
1. Write a class like:
import org.junit.*;
import static org.junit.Assert.*;
/** A JUnit test class for the class T. */
public class TTest {
/** Runs the tests. */
public static void main(String[] args) {
org.junit.runner.JUnitCore.main(“T")
}
<test methods go here, e.g.,>
@Test
public void testM1() { … }
}
22
Basic Usage of JUnit (Cont.)
2. Compile T.java and TTest.java, e.g.,
$ javac T.java TTest.java
3. Run the JUnit in IDE such as Eclipse, e.g.,
Select Run As > JUnit Test
or
Run the text interface
$ java TTest
4. Look at the failures and errors
23
Naming Convention
Test methods start with “test”
e.g., testIsqrt, testMin
Test classes end with “Test”
e.g., IMathTest, ForYouTest
24
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
Fail a test
assertNull(a)
assertSame(a,b)
assertTrue(a)
fail()
- Static methods defined in org.junit.Assert
- Variations taking string error messages
25
Testing Exceptions
Use optional parameter “expected” of
@Test annotation
Q: Without using “expected”?
@Test(expected=IndexOutOfBOundsException.class)
public void indexingEmptyList() {
new ArrayList<Object>().get(0);
}
26
More on JUnit -- Test Fixture
Sharing test data among test methods
public class TTest {
// test fixture variables, i.e., fields shared by several test methods.
@Before
public void setUp() throws Exception {
// initialize test fixture variables.
}
@After
public void tearDown() throws Exception {
// uninitialize test fixture variables.
}
// test methods …
}
Also refer to @BeforeClass and @AfterClass annotations.
27
Example
public class PointTest {
private Point p;
@Before
public void setUp() {
p = new Point(10, 10);
}
@Test
public void testSetX() {
p.setX(20);
assertEquals(20, p.getX());
assertEquals(10, p.getY());
}
Q: What if @Before
is omitted and
p is initialized to
new Point(10,10)?
@Test
public void testSetY() {
p.setY(30);
assertEquals(30, p.getY());
assertEquals(10, p.getX());
}
}
28
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.
29
Example
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
PlaceTest.class,
BattleshipTest.class,
BattleFieldTest.class
})
public class AllTests {
}
In Eclipse,
- Select a source code folder
- Right click (pop-up menu)
- Select New > Other … > JUnit > Junit Test Suite
30
More on JUnit?
Refer to www.junit.org
31