Transcript JUnit 4

JUnit

4 26-Apr-20

Comparing JUnit 3 to JUnit 4

 All the old assertXXX 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

the class is first loaded method to be executed

just once,

when  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,

cleanup after all the tests have been completed to do } @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 assertXXX 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) the same tests with multiple datasets

@RunWith(value=Parameterized.class)

public class FactorialTest { private long expected; private int value; and a @Parameters method, you can run

@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 Hence, the 4 no longer exists for primitives, only for objects 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