December 09, 2004 - TDD and Agitation

I have been doing Test Driven Development (TDD) for about four years now and agitating for a little less (it's my second anniversary as an agitator today) and I have thought a lot about how to marry the two testing styles. A discussion on the TDD mailing list today (http://groups.yahoo.com/group/testdrivendevelopment/) finally gave me a name for what I have been doing for a while. The discussion centered around the relative merits of TDD versus Design by Contract (DbC) and a surprising - surprising to me anyway - number of people said that two are complementary and that they do both. That's exactly what I have been doing without realizing it.

Here's what I do :

  1. I write almost all of my code test first using JUnit in the style described by Kent Beck in Test Driven Development.
  2. When a class emerges and looks like it should be stable for a while, I agitate it.
  3. Agitator inevitably finds a boundary condition or a permutation of inputs that I did not think to test for. I go back to JUnit and add tests for those cases. The coverage information that agitator provides is helpful here too.
  4. As a last step, I scan all the observations and check the ones that should be universally true. I also add any other invariants that occur to me. This is the DbC phase.

In math, I was always taught to specialize until the general case becomes apparent. This is what TDD teaches us. Each JUnit test becomes a special case. It's easier to grok the special cases and it's easier to do the required setup for a special case. However it's often hard to see the general rule from a collection of special cases and that's where DbC comes in. Agitator is good at finding and enforcing the general rule - it will even check that the general rule holds as each individual JUnit case runs.

Here's an example, I wrote a custom LayoutManager recently and I started in the usual way. What happens if there are no components? What happens if there is one component? Two? and so on. At the end, I started to write a test for the general case - but the resulting test was almost a duplicate of the code in my actual LayoutManager. Instead, I switched to the Agitator and added a set of invariants and got the best of both worlds.

On several occasions in the past, I have found myself discussing testing with another developer and we were just completely unable to understand each other's point because we had different world views. He was seeing from a DbC point of view while I was seeing from a TDD point of view. In his view, TDD could never work because it could never cover all the cases. In my view, it was too hard to come up with invariants that were strong enough to be both useful and universally true. As is often the case, we were equally right and wrong. Both are useful and the combination of the two is very powerful - and that's what I do.


Posted by Kevin Lawrence at December 9, 2004 01:20 PM


Trackback Pings

TrackBack URL for this entry:
http://www.developertesting.com/mt/mt-tb.cgi/132


Comments

Post a comment




Remember Me?