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