to**********@ho tmail.com (Tom Verbeure) writes:
so I'm now convinced that unit testing is really the way to go and I
want to add it to an existing project. The first thing that I find
out, is that, well, it's hard work. Harder than writing the real
functional code.
Graphs aside, it's easier 1. when you write them before you write the
code 2. when you get some practice (of course).
[...] I'm not sure, though, at what level I have to write unit tests. It's
easy to write a tests that validates the consistency of a single node
of a graph, but the real complexity is, of course, in the interaction
of multiple nodes.
[...]
Test at both levels. Also, even for a graph object containing nodes
(if that's how it's written), it can make sense to test the graph
object independently of the nodes. Sometimes you look at tests like
that and think "how could that possibly fail?", but it's surprising
how often they do if you do any refactoring (and even bug fixing,
sometimes). This is related to "mock objects", though I think mock
objects are worth avoiding if they don't turn out to be necessary.
I certainly don't like to put this forward as a beacon of good
practice, but I was quite unhappy with the tests in ClientForm (too
long, too apparently repetitive and trivial), *until* I wanted to port
it from an event-based HTML parser to a DOM. I was amazed at the
number of tests that failed in subtle ways. If I didn't have the
tests, I would never have finished it, I'm quite sure, and the tests I
thought were not pulling their weight turned out to be valuable.
Elegant graph algorithms and messy W3C standards (both HTML DOM and
HTML are quite nasty) are different things, and the latter has more to
benefit from unit tests, but I think it's worth experimenting with the
more paranoid end of unit testing. One thing I don't do and I'm quite
sure is valuable is code coverage measurement, so if I were starting
afresh I'd be attracted to amk's framework (though there are several
tools to do it with unittest -- they're just not integrated to make it
trivial).
As a BTW, one interesting thing about moving from an event parser to a
DOM (and kept the old implementation: the event-based code is still in
use) was that the unit-test nature of some of the tests was actually a
hindrance to getting the tests running, and a barrier to
maintainability . Necessary background: the module parses HTML to get
a list of HTMLForm objects; HTMLForms contain Control objects
(controls are things like text entry boxes, buttons, menus,
checkboxes). Now, my tests of the various Controls constructed
Controls directly rather than using the parser -- these were supposed
to be unit tests, after all, so I didn't want to be testing the
Controls *and* the parser at the same time. The problem, of course,
was (still is, I haven't fixed it yet) that when I started using the
DOM, the constructors for the Control objects changed completely, and
I had to fork the test code in a nasty way just to get the tests to
run. If I'd just been lazy and used the parser interface to build
Control objects, I could have run the tests with almost no changes.
Not entirely sure what the moral of this story is yet... maybe just.
John