Re: JavaDocs vs. Tests (was: Interview)
On Sun, 4 Oct 2009, Kenneth P. Turvey wrote:
On Sun, 04 Oct 2009 12:03:43 +0200, Ed Kirwan wrote:
How many units tests would be necessary to test that method? Maybe 2? 3?
How would a developer get more useful information from these 2 or 3 unit
tests than from the description above?
Certainly it would be a few.
I'd want to test, and really ought to write a separate test method for,
each of:
- adding an empty collection, and checking that it's a no-op (and doesn't
crash!)
- adding a collection with a small number of things in, and checking that
the answer comes out right
- possibly adding a collection with a large number of things in,
particularly if i knew something about the implementation of the
collection implementation under test (eg if it was an ArrayList, i'd want
to add enough that it would trigger a grow of the array)
- adding several collections in a row
- adding a null collection and getting a NullPointerException, with the
collection under test remaining unchanged
All of these are about two lines. The several-collections one is more. In
fact, the code looks like:
private Collection<String> coll;
@Before
public void createCollection() {
coll = CREATE SOME KIND OF COLLECTION
}
@Test
public void testAddAllWithEmptyCollection() {
coll.addAll(Collections.emptySet());
assertTrue(coll.isEmpty());
}
@Test
public void testAddAllWithSmallCollection() {
coll.addAll(Arrays.asList("a", "b", "c"));
assertEquals(Arrays.asList("a", "b", "c"), coll);
}
@Test
public void testAddAllWithLargeCollection() {
coll.addAll(Arrays.asList(HUGE_STRING_ARRAY));
assertEquals(Arrays.asList(HUGE_STRING_ARRAY), coll);
}
@Test
public void testAddAllWithSeveralSmallCollection() {
coll.addAll(Arrays.asList("a", "b", "c"));
coll.addAll(Arrays.asList("do", "re", "me"));
coll.addAll(Arrays.asList("1", "2", "3"));
coll.addAll(Arrays.asList("baby", "you", "and", "me"));
assertEquals(Arrays.asList("a", "b", "c", "do", "re", "me", "1", "2", "3", "baby", "you", "and", "me")), coll);
}
@Test(expected=NullPointerException.class)
public void testAddAllThrowsNullPointerExceptionWithNullCollection() {
coll.addAll(null);
}
It's certainly longer than the javadoc. But it's pretty clear, no?
Looking back over that, i should also do the first three with a test
collection that already has things in it, to make sure empty collections
aren't a special case.
Also, does your friend write JavaDoc comments for her unit tests?
I don't believe so.
You mention that the unit tests will stay current; I presume you mean
that any changes in the method under test will force the unit test to
change if required, whereas no compiler forces JavaDoc description to
keep step with the described method. Which is fair enough.
Finally, you mention that the unit tests take no extra effort to
maintain if you're going to write them anyway; isn't the same true for
JavaDoc comments?
I think the point is that you *are* going to write unit tests anyway.
Whatever you feel about documentation, they aren't optional. And since you
do have unit tests, can you dispense with javadoc comments?
Python has a rather funky tool called doctest:
http://docs.python.org/library/doctest.html
Which looks through your doc comments (python's equivalent of javadoc,
which are available at runtime) looking for anything that looks like a
transcript of a session with the interpreter, then runs the input, and
verifies that the output is the same. Transcripts are a very common way of
giving examples of what a function does in python, so this gives you some
unit testing 'for free', and at the same time verifies that your
documentation is accurate.
tom
--
The best way to predict the future is to invent it. -- Alan Kay