This post originated from an RSS feed registered with Java Buzz
by Geoffrey Wiseman.
Original Post: JUnit Extension and Template Method
Feed Title: Furious Purpose
Feed URL: http://www.jroller.com/diathesis/feed/entries/rss
Feed Description: Thoughts and experiences on technology and software.
JUnit is a framework intended for extension. At its most basic, a typical
JUnit test case extends the junit.framework.TestCase class. Development
teams often extend JUnit's base test case class with alternatives of their
own that are specific to a project or to a particular kind of testing.
Other teams create full-blown extensions that supply a great deal of
additional functionality to JUnit.
I've seen a number of these extensions over the years, and many of them,
particularly the home-brew ones, suffer from one basic problem: redefining
the template method contract that JUnit supplies for setting up or tearing
down a test case. This can happen in one of two ways: by renaming the
template methods or by requiring that the superclass template methods be
called.
Required super.xxxXxx()
If you're writing an extension to TestCase that requires its own setup or
teardown code, the simplest way is to implement the setUp() and tearDown()
methods in the superclass itself, and rely on the programmers who use the
test case to call super.setUp() and super.tearDown(). After all, developers
should know when to call superclass methods when inheriting, right? Wrong.
Because JUnit goes out of its way to create these two methods as
template methods,
it's generally assumed that the super() methods are simply placeholders for
the developer's own setup and teardown functionality. If they've used JUnit
for any length of time, they're likely to be used to overriding setUp() and
tearDown() without regard for the superclass.
So if you write your extension this way, they're likely to forget, at least
some of the time, to call your superclass methods, which may well cause their
tests to fail, possibly in unpredictable ways that are difficult to diagnose.
Renaming the Template Methods
Having suffered through the use of a few forgotten super.setUp() methods, a
developer's next instinct is often to repeat the template method pattern in
their own test case extension, by declaring setUp() and tearDown() to be
final and calling two new template methods, say, setUpMyExtension() and
tearDownMyExtension(). This is reasonable, and I prefer it to
the aforementioned super.method() approach, but it's still a little lacking.
Again, an experienced JUnit developer has written hundreds or thousands of
JUnit tests and is pretty used to setUp() and tearDown(). The compiler will,
at least, warn them of their folly as they try and compile their newly written
tests, but this may be a source of constant frustration.
Happily, there are other alternatives.
Override RunBare
This is the approach I typically take when writing my own base test cases;
it's simple, and avoids breaking the template method contract with which JUnit
developers are familiar.
public class MyExtensionTestCase
{
public void runBare( ) throws Throwable
{
setUpMyExtension();
super.runBare();
tearDownMyExtension();
}
public void setUpMyExtension()
{
// whatever setup code I need here
}
public void tearDownMyExtension()
{
// whatever teardown code I need here
}
}
This leaves the normal JUnit setUp() and tearDown() methods available to
be overridden in typical template method form, not worrying about the
details of the way in which my superclass test case sets itself up or
tears itself down.
Use TestNG
Cedric's TestNG
is another alternative, with attribute-declared setup and
teardown methods that needn't rely on the template method approach to get
the job done. (I'm still waiting for an
Eclipse plugin to give it a
thorough shot, Cedric. How's that coming along? Is it coming along?)
Other
I'm sure there are still other approaches that I haven't laid out here --
free to drop me a comment or leave a trackback if you think yours is worth
a mention.