JUnit best practices (II)

上一篇 / 下一篇  2008-02-01 21:07:05

JUnit best practices

Techniques for building resilient, relocatable, multithreaded JUnit tests

Page 2 of 5

Don't assume the order in which tests within a test case run

You should not assume that tests will be called in any particular order. Consider the following code segment:

public class SomeTestCase extends TestCase {
   public SomeTestCase (String testName) {
      super (testName);
   }
   public void testDoThisFirst () {
     ...
   }
   public void testDoThisSecond () {
   }
}


In this example, it is not certain that JUnit will run these tests in any specific order when using reflection. Running the tests on different platforms and Java VMs may therefore yield different results, unless your tests are designed to run in any order. Avoiding temporal coupling will make the test case more robust, since changes in the order will not affect other tests. If the tests are coupled, the errors that result from a minor update may prove difficult to find.

In situations where ordering tests makes sense -- when it is more efficient for tests to operate on some shared data that establish a fresh state as each test runs -- use a staticsuite()method like this one to ensure the ordering:

public static Test suite() {
   suite.addTest(new SomeTestCase ("testDoThisFirst";));
   suite.addTest(new SomeTestCase ("testDoThisSecond";));
   return suite;
}


There is no guarantee in the JUnit API documentation as to the order your tests will be called in, because JUnit employs aVectorto store tests. However, you can expect the above tests to be executed in the order they were added to the test suite.

Avoid writing test cases with side effects

Test cases that have side effects exhibit two problems:

  • They can affect data that other test cases rely upon
  • You cannot repeat tests without manual intervention


In the first situation, the individual test case may operate correctly. However, if incorporated into aTestSuitethat runs every test case on the system, it may cause other test cases to fail. That failure mode can be difficult to diagnose, and the error may be located far from the test failure.

In the second situation, a test case may have updated some system state so that it cannot run again without manual intervention, which may consist of deleting test data from the database (for example). Think carefully before introducing manual intervention. First, the manual intervention will need to be documented. Second, the tests could no longer be run in an unattended mode, removing your ability to run tests overnight or as part of some automated periodic test run.

Call a superclass's setUp() and tearDown() methods when subclassing

When you consider:

public class SomeTestCase extends AnotherTestCase {
   // A connection to a database
   private Database theDatabase;
   public SomeTestCase (String testName) {
      super (testName);
   }
   public void testFeatureX () {
      ...
   }
   public void setUp () {
      // Clear out the database
      theDatabase.clear ();
   }
}


Can you spot the deliberate mistake?setUp()should callsuper.setUp()to ensure that the environment defined inAnotherTestCaseinitializes. Of course, there are exceptions: if you design the base class to work with arbitrary test data, there won't be a problem.   (Continued)


TAG:

 

评分:0

我来说两句

Open Toolbar