Would you blame the hammer because the nail is blunt?

Cedric’s having another go at JUnit Again he misses the point: extensions to JUnit are not JUnit itself, and JUnit can’t be blamed for people extending it to the wrong way.


His current complaint is about how certain extensions to JUnit override setUp(), forcing you to call super.setUp() in your own testcases. This is certainly a problem; but it’s not JUnit’s problem. The problem is how the extensions have implemented themselves.

Essentially, they’ve been lazy: they’ve supplied implementations of setUp() and tearDown(), and decreed that all users of the extension need to make sure they are call. This is wrong!

What the extension developers should have overridden was the runBare() method or the runTest() method. They could then have put in their own setup/teardown code without impacting the client. Here’s an example:

/** Override runBare to call mySetup() first, myTearDown() last */
public void runBare() throws Throwable {
  try {
    mySetup();
    super.runBare();
  } finally {
    myTearDown();
  }
}

This calls the extension’s setup and teardown methods before doing the ones for the test case; overriding runTest() in a similar manner will result in the extension methods being called after the test case’s setup.

Cedric is “actually shocked that JUnit forces you to use this anti-pattern”. Well, Cedric, it doesn’t. It’s the developers of JUnit extensions who do this, not the JUnit guys themselves.

Look, folks, here’s the right way to make a JUnit extension.

  1. Create an instance of TestDecorator (or the subclass, TestSetup Put functionality in here so someone can use your extension without changing their inheritance hierarchy.
  2. Then, after doing that, create a subclass of TestCase which delegates down to the decorator as needed. Use the above mechanism to avoid putting additional constraints on client subclasses.

This isn’t rocket science, people.

Advertisements

Author: Robert Watkins

My name is Robert Watkins. I am a software developer and have been for over 18 years now. I currently work for people, but my opinions here are in no way endorsed by them (which is cool; their opinions aren’t endorsed by me either). My main professional interests are in Java development, using Agile methods, with a historical focus on building web based applications. I’m also a Mac-fan and love my iPhone, which I’m currently learning how to code for. I live and work in Brisbane, Australia, but I grew up in the Northern Territory, and still find Brisbane too cold (after 16 years here). I’m married, with two children and one cat. My politics are socialist in tendency, my religious affiliation is atheist (aka “none of the above”), my attitude is condescending and my moral standing is lying down.

6 thoughts on “Would you blame the hammer because the nail is blunt?”

  1. I have noticed several cases of people paying out on junit in appropriately – I wonder if it is connected to the push towards other frameworks like TestNG (too much conspiracy theory ?).

    Some people have said that junit is “old” as any development/contributions have stopped – but isn’t that just a sign of maturity in a tool that is used pretty much everywhere? (and nicely integrated to every java IDE).

  2. IMHO, it’s a combination of annoyance and ignorance. People are rightfully annoyed that some popular JUnit extensions are awkward to use (I know StrutsTestCase fits in here, for example). They assume that’s because of JUnit.

    They also assume that some _convenience_ features (such as the testXYZ convention) are actually constraints, when they aren’t. See my earlier post of JUnit’s architecture for more.

  3. I totally agree Robert and have been grumbling about this for while – I don’t see what’s so bad about JUnit that you need to go write another framework. It’s actually a pretty simple (as in small) API – there’s not much to it!! It’s ideal for writing *unit* tests (to me, using the extensions takes you out of purist Unit testing and into integration / acceptance testing – but the extensions are very useful). Forget jumping on the next bandwagon – just because something’s been around for a while doesn’t mean it’s out of date. Ok, if you WANT to write a new framework fine, but don’t try to promote it by putting down the existing framework – it gives ignorant people the wrong idea 😉

  4. One of the nice things about JUnit is that it effectively resets everything with each test method invokation (calling setUp and tearDown and so on).

    This means that each test method is like a test on its own, and the TestCase class is just a logical collection of related tests. It is a bit wierd at first, but it actually makes things much simpler.

    NUnit doesn’t seem to work that way, and is confusing me because of it.

  5. JUnit makes one instance of the test case class per instance; this means that tearDown, in particular, is more about resource management than test isolation.

    NUnit (and TestNG) uses one instance of the test case class only. Isolation needs to be enforced by the tearDown()/setUp() (resetting variables, etc). Apparently, the main designer of NUnit now has had second thoughts about this difference (which is quite intentional).

  6. I tried to think up an anagram(?) for TestNG that said that it was “just another need for an xml file to write/maintain”, but couldn’t do it.

    Shame.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s