JUnit 4

shopfitterpsithurismΛογισμικό & κατασκευή λογ/κού

10 Νοε 2012 (πριν από 5 χρόνια και 8 μέρες)

199 εμφανίσεις

16
-
Mar
-
13

JUnit
4

Comparing JUnit 3 to JUnit 4


All the old
assert
XXX

methods are the same


Most things are about equally easy


JUnit 4 makes it easier to test that exceptions are thrown when
they should be


JUnit 4 can still run JUnit 3 tests


JUnit 4 provides protection against infinite loops


JUnit 4 has some additional features



Migrating from JUnit 3


JUnit 4 requires Java 5 or newer


Don’t extend
junit.framework.TestCase
; just use an ordinary
class


Import
org.junit.*

and
org.junit.Assert.*


Use a
static

import for

org.junit.Assert.*


Static imports replace inheritance from
junit.framework.TestCase


Use annotations instead of special method names:


Instead of a
setUp

method, put
@Before

before some method


Instead of a
tearDown

method, put
@After

before some method


Instead of beginning test method names with ‘
test
’, put
@Test

before
each test method

Writing a JUnit test class, I


Start by importing the JUnit 4 classes you need


import org.junit.*;

import
static

org.junit.Assert.*;



Declare your class in the usual way


public class MyProgramTest {



Declare any variables you are going to use frequently,
typically including an instance of the class being tested


MyProgram program;

int [] array;

int solution;

Writing a JUnit test class, II


If you wish, you can declare
one

method to be executed
just once,

when
the class is first loaded


This is for expensive setup, such as connecting to a database


@BeforeClass

public static void setUpClass() throws Exception {


// one
-
time initialization code

}



If you wish, you can declare
one

method to be executed
just once,

to do
cleanup after all the tests have been completed


@AfterClass

public static void tearDownClass() throws Exception {


// one
-
time cleanup code

}

Writing a JUnit test class, III


You can define one or more methods to be executed before each test;
typically such methods initialize values, so that each test starts with a fresh
set


@Before

public void setUp() {


program = new MyProgram();


array = new int[] { 1, 2, 3, 4, 5 };

}



You can define one or more methods to be executed after each test;
typically such methods release resources, such as files


@After

public void tearDown() {

}

@Before

and
@After

methods


You can have as many
@Before

and
@After

methods
as you want


Be warned: You don’t know in what order they will execute


You can inherit
@Before

and
@After

methods from a
superclass; execution is as follows:


Execute the
@Before

methods in the superclass


Execute the
@Before

methods in this class


Execute a
@Test

method in this class


Execute the
@After

methods in this class


Execute the
@After

methods in the superclass

Writing a JUnit test class, IV


A test method is annotated with
@Test
, takes no parameters,
and returns no result


All the usual
assert
XXX

methods can be used


@Test

public void sum() {


assertEquals(15, program.sum(array));


assertTrue(program.min(array) > 0);

}

Special features of
@Test


You can limit how long a method is allowed to take


This is good protection against infinite loops


The time limit is specified in milliseconds


The test fails if the method takes too long


@Test (timeout=10)


public void greatBig() {


assertTrue(program.ackerman(5, 5) > 10e12);

}




Some method calls should throw an exception


You can specify that a particular exception is expected


The test will pass if the expected exception is thrown, and fail otherwise


@Test (expected=IllegalArgumentException.class)

public void factorial() {


program.factorial(
-
5);

}

Parameterized tests


Using
@RunWith(value=Parameterized.class)

and a
@Parameters

method, you can run
the same tests with multiple datasets


@RunWith(value=Parameterized.class)

public class FactorialTest {


private long expected;


private int value;



@Parameters


public static Collection data() {


return Arrays.asList( new Object[ ][ ] { { 1, 0 }, { 1, 1 }, { 2, 2 }, { 120, 5 } });


}



public FactorialTest(long expected, int value) {
// constructor


this.expected = expected;


this.value = value;


}



@Test


public void factorial() {


assertEquals(expected, new Calculator().factorial(value));


}

}


Source: http://today.java.net/pub/a/today/2006/12/07/junit
-
reloaded.html

Ignoring a test


The
@Ignore

annotation says to not run a test


@Ignore("I don’t want Dave to know this doesn’t work")

@Test

public void add() {


assertEquals(4, program.sum(2, 2));

}


You shouldn’t use

@Ignore
without a very good reason!

Test suites


As before, you can define a suite of tests


@RunWith(value=Suite.class)

@SuiteClasses(value={MyProgramTest.class,


AnotherTest.class})

public class AllTests { … }

Other stuff


Failed tests now throw an
AssertionError
, rather than JUnit 3’s
AssertionFailedError



There is now a version of
assertEquals

for arrays of objects:

assertEquals(Object[] expected, Object[] actual)


Unfortunately, there is still no
assertEquals

for arrays of primitives



JUnit 3 had an
assertEquals(
p
,
p
)
method for each kind of
primitive
p
, but JUnit 4 only has an
assertEquals(
object
,
object
)

and depends on autoboxing

A gotcha


The following method:


long sum(long x, long y) { return x + y; }


with the following test:


@Test

public void sum() {


assertEquals(4, s.sum(2, 2));

}


gives:


expected: <4> but was: <4>


This is due to your friend, autoboxing


assertEquals

no longer exists for primitives, only for objects


Hence, the
4

is autoboxed to an
Integer
, while
sum

returns a
long


The error message means: expected int 4, but got long 4


To make this work, change the
4

to a
4L

JUnit 4 in Eclipse and NetBeans


As usual, the easiest way to create a test class is just to let your
IDE do it for you


Here is the recommended test
-
driven approach


Create a class containing all the “stub” methods you initially think you will
need


Have the IDE create the test class, with all the test methods


Repeat:


Write a test


Make sure the test fails


Write the method being tested


Make sure the test now succeeds


Note: When you create the test class, NetBeans in particular puts
a lot of garbage lines into each test method; you can just delete
these and put in your own code

The End