A great New Idea for solving the JUnit dependency problem!
Posted on March 19th, 2005 by pcal
I just stumbled across an older
blog entry
blog entry about JUnit which has helped me better understand the core of the debate over test dependencies. The article presents a justification for JUnit's practice of instantiating a new TestCase instance for every test method it runs. It leads off with an example:
public class Tester extends TestCase {
public Tester(String name) {super(name);}
private List list = new ArrayList();
public void testFirst() {
list.add("one");
assertEquals(1, list.size());
}
public void testSecond() {
assertEquals(0, list.size());
}
}
and provides the following explanation about it:
Some people may not realize this, but both tests pass - and will pass in whichever order they are run. ... One of the key principles in JUnit is that of isolation - that is no test should ever do anything that would cause other tests to fail.
And I do kind of see his point: having all that shared data can definitely lead to fragile code if you aren't careful in the design of your class.
This got me to thinking, though: wouldn't it be great if Java had a way to declare a variable that could only be used *inside* a method? Sounds cool, huh? Maybe I should start a JSR for these things - I think I will call them "Local Variables."
These Local Variables would would be a huge win for JUnit users because they would offer a much simpler way to ensure that test methods operate on fresh data. Let me illustrate how I would see this working in the previous example - try to stay with me:
public class Tester extends TestCase {
public Tester(String name) {super(name);}
public void testFirst() {
List list = new ArrayList();
list.add("one");
assertEquals(1, list.size());
}
public void testSecond() {
List list = new ArrayList();
assertEquals(0, list.size());
}
}
Isn't that great? Wouldn't it be awesome if we could write tests this way?
</snotty>
Ok, ok, you get the point (I hope). And please don't get me wrong - I like JUnit and have found it very useful, modulo a few annoyances like this.
But the bottom line is that this whole 'test independence' feature that JUnit offers is rooted in a conflation of local and member variables. If you want to have state that is local to a method invocation, Java gives you a perfectly good way to do this.
But Java also gives you a mechanism for associating state with an instance, and there are plenty of valid reasons to want to use it when writing tests. Managing the state of an instance is a fundamental part of OO programming, and competent OO programmers know how to do it without making a mess of things.
By taking away instance variables, JUnit effectively insists that its users are not competent OO programmers. I find this just slightly irksome.
What I find disturbing is that so many JUnit users so vehemently
seem to agree.
Fields and local variables in test methods
Patrick has posted an interesting and novel way to look at this "dependent test methods" problem……