Test-wide Setup and Tear Down of JUnit Tests

JUnit 4.0 introduces the @BeforeClass annotation, providing a way to run a class-wide setup method before any of the tests in that class are run. The analogous @AfterClass annotation allows for tear down of those fixtures. I work on a project that hasn’t yet upgraded to JUnit 4.0, and although less widely publicized, it is possible to accomplish the same thing with 3.8.x.

Think before doing this. Tests should be independent of one another. If your tests share fixtures, side effects from one test could affect the results of others. Sometimes, however, a test fixture is just too expensive to set up and tear down with every test. In my case, I needed to set up a database and import a substantial quantity of data. Doing this for every test would’ve made the suite prohibitively slow.

The TestSetup class makes test-wide setup and tear down possible in JUnit 3.8.x. Consider the following class:

	package com.burningvoid.jexample;

	import junit.framework.Test;
	import junit.framework.TestCase;
	import junit.framework.TestSuite;
	import junit.textui.TestRunner;

	public class ExampleTestCase extends TestCase {

		public void setUp() {
			System.out.println("Per Test Case Setup");
		}

		public void tearDown() {
			System.out.println("Per Test Case Teardown");
		}

		public void testA() {
			System.out.println("Test A");
		}

		public void testB() {
			System.out.println("Test B");
		}

		public static Test suite() {
			return new TestSuite(ExampleTestCase.class);
		}

		public static void main(String[] args) {
			TestRunner.run(suite());
		}
	}

If I run this class, the setUp and tearDown methods run once before each test, producing output of:

.Per Test Case Setup
Test A
Per Test Case Teardown
.Per Test Case Setup
Test B
Per Test Case Teardown

For those accustomed to IDE support for JUnit, the periods in the output are due to the text JUnit test runner. It prints a period for each test.

Ok, now change the suite() method to the following:

	public static Test suite() {
		TestSuite ts = new TestSuite();
		ts.addTestSuite(ExampleTestCase.class);
		return new ExampleTestSetup(ts);
	}

This requires the addition of another class.

	package com.burningvoid.jexample;

	import junit.extensions.TestSetup;
	import junit.framework.Test;

	public class ExampleTestSetup extends TestSetup {

		public ExampleTestSetup(Test test) {
			super(test);
		}

		public void setUp() {
			System.out.println("Test-wide setup");
		}

		public void tearDown() {
			System.out.println("Test-wide teardown");
		}
	}

The TestSetup decorator’s setUp and tearDown methods are called before and after all the tests in the suite, resulting in the following output.

Test-wide setup
.Per Test Case Setup
Test A
Per Test Case Teardown
.Per Test Case Setup
Test B
Per Test Case Teardown
Test-wide teardown

If you need test setup and tear down that covers more than one class, simply create a top level test suite that collects all of your test classes into one decorated suite, such as:

	public static Test suite() {
		TestSuite ts = new TestSuite();
		ts.addTestSuite(ExampleTestCase.class);
		ts.addTestSuite(SomeOtherTestCase.class);
		ts.addTestSuite(YetAnotherTestCase.class);
		return new ExampleTestSetup(ts);
	}

As far as I know, the @BeforeClass and @AfterClass mechanisms aren’t quite as flexible, in that they only apply to a single class, and thus can’t be applied to an entire suite. I say this not having used JUnit 4.0 yet, though, so please correct me if I’m incorrect about this.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • Furl
  • NewsVine

3 Responses to “Test-wide Setup and Tear Down of JUnit Tests”

  1. cnc dude says:

    this language except for some syntax looks like c#, i am unfamiliar with it though, i see how the two methods work but dont understand the @ classes. could you explain that more? your basically saying these two new methods are useless?

  2. jeffrey says:

    The language is Java. To understand @BeforeClass and @AfterClass, take a look at the documentation for Java annotations, at http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html

    I’d take a shot at explaining, but most of the coding I’m doing these days is in Ruby, so I’d probably miss something important if I tried to provide an answer myself.

    I don’t think that @BeforeClass and @AfterClass are useless. They just didn’t do what I wanted to do in that set of tests. The annotations would’ve allowed me to set up a set of test conditions covering several methods within a class, but I was looking for a way to set up test fixtures for an entire test run.

  3. ratzusca says:

    I found your post very useful. Is one of the few posts on the matter. Thanks a lot.

Leave a Reply

Subscribe without commenting