JUnit best practices (I)

上一篇 / 下一篇  2008-02-01 20:57:09

JUnit best practices

Techniques for building resilient, relocatable, multithreaded JUnit tests

JUnit is a typical toolkit: if used with care and with recognition of its idiosyncrasies, JUnit will help to develop good, robust tests. Used blindly, it may produce a pile of spaghetti instead of a test suite. This article presents some guidelines that can help you avoid the pasta nightmare. The guidelines sometimes contradict themselves and each other -- this is deliberate. In my experience, there are rarely hard and fast rules in development, and guidelines that claim to be are misleading.

We'll also closely examine two useful additions to the developer's toolkit:

  • A mechanism for automatically creating test suites from classfiles in part of a filesystem
  • A newTestCasethat better supports tests in multiple threads



When faced with unit testing, many teams end up producing some kind of testing framework. JUnit, available as open source, eliminates this onerous task by providing a ready-made framework for unit testing. JUnit, best used as an integral part of a development testing regime, provides a mechanism that developers can use to consistently write and execute tests. So, what are the JUnit best practices?

Do not use the test-case constructor to set up a test case

Setting up a test case in the constructor is not a good idea. Consider:

public class SomeTest extends TestCase
   public SomeTest (String testName) {
      super (testName);
      // Perform test set-up
   }
}



Imagine that while performing the setup, the setup code throws anIllegalStateException. In response, JUnit would throw anAssertionFailedError, indicating that the test case could not be instantiated. Here is an example of the resulting stack trace:

junit.framework.AssertionFailedError: Cannot instantiate test case: test1       at
junit.framework.Assert.fail(Assert.java:143)     at
junit.framework.TestSuite.runTest(TestSuite.java:178)  at
junit.framework.TestCase.runBare(TestCase.java:129)      at
junit.framework.TestResult.protect(TestResult.java:100)        at
junit.framework.TestResult.runProtected(TestResult.java:117)     at
junit.framework.TestResult.run(TestResult.java:103)      at
junit.framework.TestCase.run(TestCase.java:120)  at
junit.framework.TestSuite.run(TestSuite.java, Compiled Code)     at
junit.ui.TestRunner2.run(TestRunner.java:429)



This stack trace proves rather uninformative; it only indicates that the test case could not be instantiated. It doesn't detail the original error's location or place of origin. This lack of information makes it hard to deduce the exception's underlying cause.

Instead of setting up the data in the constructor, perform test setup by overridingsetUp(). Any exception thrown withinsetUp()is reported correctly. Compare this stack trace with the previous example:

java.lang.IllegalStateException: Oops     at bp.DTC.setUp(DTC.java:34)   at
junit.framework.TestCase.runBare(TestCase.java:127)      at
junit.framework.TestResult.protect(TestResult.java:100)        at
junit.framework.TestResult.runProtected(TestResult.java:117)     at
junit.framework.TestResult.run(TestResult.java:103)
...



This stack trace is much more informative; it shows which exception was thrown (IllegalStateException) and from where. That makes it far easier to explain the test setup's failure.   (Continued)


TAG:

 

评分:0

我来说两句

Open Toolbar