Test First Programming -- Some Personal Experiences

For me, it all started -- as many things start -- with a trip to a local bookstore, those wonderful places where I can be a geek and a parent at the same time. I was looking through the magazines when a Software Development article caught my eye, Martin Fowler's "Is Design Dead". Fowler wrote about the tension between his career as an author of books on software design (e.g. UML distilled) and his new interest in eXtreme Programming. On the basis of this article, I picked up Kent Beck's Extreme Programming Explained to learn more about this fascinating idea.

As I read the book, it was obvious why such a thing would catch on: suddenly it was OK to be a programmer again. Here was someone with the temerity to suggest that we write code in code -- moreover that we have a methodology of writing code in code. Those of us like me who never found in code something to be ashamed of were bound to like such a thing.

This was radical stuff. Set against the backdrop of the waterfall shop that paid my bills -- this was extreme.

I didn't use all of it, nor plan to. The pair programming stuff looked a bit odd, rather like a State truck (four guys drinking coffee -- one guy digging a hole). A colleague and I were in the habit of bouncing ideas off one another constantly, but we still used independent keyboards. I'm not that much an eXtreme programmer -- or any other kind of religious programmer. If anything, I'm a "pragmatic" programmer, but if Andrew Hunt and David Thomas ever elevate pragmatism to the status of a movement I'll quit being that too. To my eclectic way of thinking, the articles claiming that eXtreme Programming was the "holy grail" of programming threatened to kibosh the whole enterprise in my eyes -- just what we need, yet another sacred cup to glimmer brilliantly in the eyes of the unfortunate newcomers to the industry who haven't yet had their fill of holy grails.

But Beck's view of testing struck a chord, especially his treatment of unit tests. These were not tests written like some test suites I'd seen -- tests that took a day of laborious comparisons to interpret. Here were simple tests written from a developer's perspective, tests that grew as the system grew and served as a constant source of feedback. It was like the habit I'd developed of running all my code through the debugger -- but better, since it ran over and over and over whenever I wanted it to with only the slightest effort.

One day then I picked up the JUnit suite and began to work with it, trying some simple asserts. A few clumsy attempts for a couple of hours were quickly cured by going over the test runner documentation again. Downloading it at the client's site again I wrote the first tests for our product -- some ini file settings had bitten me once, so I started out simple, testing the ini file's existence and some basic properties. Working on a fairly complex set of steps for a user logon, naturally I coded several logon related tests and added them to the suite.

Soon the process of testing started changing the way I worked. Freed from the need to integrate constantly in order to run the most simple tests, I could develop whole subsystems more easily, more intelligently. Soon an entire body of code, whose only rationale seemed to be to allow developers "hooks by which to debug" -- disappeared. With it went the requirement of debugging at a special machine -- a goal I'd had since joining this client. I was now routinely debugging at my workstation. Though free from the need to integrate constantly, I was actually doing so more since I was more productive.

The test suite helped me develop many new pieces of code -- and allowed me to verify changes I felt I needed to make just before and just after I made them, with practically no effort at all. I developed a properties file of test cases that each test could use, these also served as test data for doing functional tests as needed. Soon other programmers on the team were writing and running tests, breaking our own and each others code with new tests and rushing to get fixes in. Sanity check, interface documentation, debugger driver, build verifier -- we began to use the tests for all these things.

As time has gone on, I've come to rely on the tests more and more. Occasionally I regret the time it takes me to maintain or improve the suite, but the next time I introduce a change to the software and use the tests to run a quick regression I usually get over that pretty quickly.