Skip to main content

JUnit 4 you

Posted by fabianocruz on June 11, 2006 at 3:01 PM PDT

I think it's quite impressive how software testing has grown in popularity in the past decade. A lot of tools (open-source and commercial) and practices such as continuous testing and integration, code coverage, static analyzers and so forth. Some of that fancy stuff you've probably heard about, they were originated, disseminated and now getting lift from agile development processes "spaceship" (e.g.: Extreme Programming, Scrum and so on). But, the agile methodologies' boom is a topic for another talk. ;)

In fact, as pointed out by Kent Beck in his presentation "TS-1580" at this year's JavaOne entitled "JUnit 4 and JavaTM EE 5: Better Testing by Design", we are now out of the Dark Ages and going into the Age of Paradox. According to Kent, in the Dark Ages (…just a few years ago), if you said to a developer, "you should write tests while developing your code", then most probably you could receive it as an answer: "You've gotta be kidding. Testing is for the QA folks". The Age of the Developer Testing Paradox (Today) is in the opposite sense, because we have a theoretical consensus which developer testing is a great idea and everyone should do it, but nevertheless, a practical reality: developer testing is still only practiced by a minority and testing is a low-status activity.

Backing to JUnit 4 framework, which is the main topic of this blog, after 3 years or so without a significant release, they have come out with the version 4.0 which was officially announced in 2006-02-16 and didn't take so long for many leading vendors to start adopting it (see "JUnit 4 Ecosystem Support" table below – please, feel free to drop a line about your preferable IDE, tool etc, status regarding JUnit 4 support).

So, the most popular and the de facto standard JavaTM unit testing framework, written by Kent Beck and Erich Gamma, became even simpler and it aims to provide an approachable (simple, easy-to-use, minimalist), flexible, responsive, extensible foundation for running and constructing solutions on top of it and to the ordinary person (this is important). I know that there will always be ways to improve frameworks like that, but I agree, it's really straightforward (thanks to JSR 175 - A Metadata Facility for the Javaâ„¢ Programming Language and it is explicit metadata in the form of annotations and those who understood that testing is fundamental to software development, also thanks to NUnit and TestNG folks for the hard work on the test space).


Tool Version Availability Comments
Eclipse IDE * ** 3.1.2 warning_2.gif You must have the new version of JUnit in your classpath
Eclipse IDE * 3.2 RC6 check.gif also supporting JUnit 4.1
NetBeans IDE * ** 5.0 warning_2.gif

http://junit.netbeans.org/junit4/first-try.html
NetBeans IDE * ** 5.5 Beta warning_2.gif

http://junit.netbeans.org/junit4/first-try.html
IntelliJ IDEA * 5.1 warning_2.gif


running-junit-4-tests-in-intellij-idea-51
Maven 2 Surefire plug-in 2.2 error.gif

Known issue: http://jira.codehaus.org/browse/SUREFIRE-31
Ant 1.6.5 error.gif

http://marc.theaimsgroup.com/?l=ant-dev&m=114595849626009&w=2

http://www.jguru.com/forums/view.jsp?EID=1290268

http://www.archivesat.com/Junit_at_Yahoogroups/thread937011.htm

Table 1: JUnit 4 Ecosystem Support

(*) Partially supported – these tools are still improving their support regarding this new version of JUnit.

(**) for NetBeans 5.0/5.5 Beta and Eclipse 3.1.2 you must include the JUnit4TestAdapter which is part of the backwards compatibility strategy.

import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;

...

  public static Test suite() {
    return new JUnit4TestAdapter(AdditionAllTests.class);
  }

...



NOTE: JUnit4TestAdapter is not required for Eclipse 3.2.

Some statistics from Sourceforge for JUnit project indicate that developers and companies in general seem to be more than convinced about the benefits of implementing unit tests: over 99% of activities and from ~17K in September 2003 (the announcement of version 3.8.1 which was a roll-up release for 3.8 with a couple of fixes) to ~66K (downloads/month) in the beginning of this year (version 4.0 announcement).

In the JUnit 4 in 10 minutes article, Gunjan Doshi is revisiting the "old" JUnit (3.8.2 and its predecessors) showing the new features available in the version 4.0. He summarizes the new JUnit style:

  • It Requires JDK 5 to run.
  • Test classes do not have to extend from junit.framework.TestCase.
  • Test methods do not have to be prefixed with ‘test’.
  • There is no difference between the old assert methods and the new assert methods.
  • Use @Test annotations to mark a method as a test case.
  • @Before and @After annotations handle set up and tear down.
  • @BeforeClass and @AfterClass annotations handle one time only set up and tear down.
  • @Test annotations can take a parameter for timeout. A test fails if it takes longer to execute.
  • @Test


  • JUnit4Adapter enables running the new JUnit4 tests using the old JUnit runners.
  • Old JUnit tests can be run in the new JUnit4 runner.

We can also include the following annotations to the above list:

  • @RunWith (org.junit.runner.RunWith)
  • @SuiteClasses (org.junit.runners.Suite.SuiteClasses)
  • @Parameters (org.junit.runners.Parameterized.Parameters)
  • @Ignore (org.junit.Ignore)

For instance, you can have both JUnit 3.x series and 4.0 coexisting in Eclipse IDE 3.1 and above. The following code illustrates how you can have both styles working together and also uses some of the new annotations presented so far:

//Old JUnit style
public class AdditionTest extends junit.framework.TestCase {

  private int x, y = 1;

  public void testAddition() {
    int z = x + y;
    assertEquals(2, z);
  }

}

//New JUnit style
public class AdditionTest2 {

  private int x, y = 1;

  @Test
  public void addition() {
    int z = x + y;
    assertEquals(2, z);
  }

}

@RunWith(Suite.class)
@SuiteClasses( { AdditionTest.class, AdditionTest2.class })
public class AdditionAllTests {

  public static Test suite() {
    return new JUnit4TestAdapter(AdditionAllTests.class);
  }

}

One more example, but now showing parameterized test in JUnit 4 and also the @Ignore annotation in action:

@RunWith(Parameterized.class)
public class AdditionTest3 {

  private int x, y;

  public AdditionTest3(int x, int y) {
    this.x = x;
    this.y = y;
  }
 
  @Test
  public void addition() {
    int z = x + y;
    assertEquals(2, z);
  }

  @Ignore
  @Test
  public void additionAgain() {
    fail("I want to temporarily disable this test");
  }

  @Parameters
  public static LinkedList data() {
    LinkedList params = new LinkedList();
    params.add(new Integer[] { 1, 3 });
    params.add(new Integer[] { 1, 1 });
    return params;
  }

}

And, last but not least, JUnit 4.1 version has been announced in 2006-04-27 (it's a bug-fix release) and according to the information available here, the changes are:

  • Bug fix: listeners now get a correct test running time, rather than always being told 0 secs.
  • The @RunWith annotation is now inherited by subclasses: all subclasses of an abstract test class will be run by the same runner
  • The build script fails if the JUnit unit tests fail
  • The faq has been updated
  • Javadoc has been improved, with more internal links, and package descriptions added (Thanks, Matthias Schmidt!)
  • An acknowledgements.txt file has been created to credit outside contributions
  • The Enclosed runner, which runs all of the static inner classes of a given class, has been added to org.junit.runners.

Concerning the last change from the above list, the Enclosed runner is quite useful and you can find a simple example below:

@RunWith(Enclosed.class)
public class EnclosedRunnerSampleTest {

  public static class Inner {
    @Test
    public void one() {
    }
    @Test
    public void two() {
    }
    @Test
    public void three() {
    }
  }

}

Conclusion:

In the past few years, we are seeing more and more programmers testing their own software and that's great. Writing unit tests doesn’t need to be boring or painful or frustrating, specially considering the huge JUnit ecosystem support, where fancy IDEs are providing nice mechanisms for developing tests. The JUnit 4 provides a clear, simple and extensible API for writing unit tests in Java.

One important thing to say is that if you are currently planning to implement your tests using JUnit 4 style, please ensure that you have the support of the right tools, otherwise, you should keep going with JUnit 3.x series.

Have fun!

For more information:

Disclaimer: I don't claim to be an expert on testing. Please send comments and corrections. ;)

Related Topics >>