Thursday, July 22, 2010

Unit Tests Rock!

While I've been a big fan of TDD for a while, I must admit that I don't always develop this way. Most applications I work on are large and have been around for many years, generally meaning that there are currently no (or very few) unit tests already in place. Inserting unit tests into an application of this type can be very overwhelming.

I am currently reading the excellent book Working Effectively With Legacy Code by Michael Feathers that details a lot of techniques to get your code under test (you can get an idea of what the book is like from this this article). While these techniques are very handy, it is still very time consuming to implement and convincing the product owners that this time is worthwhile can be very difficult, especially for a legacy application as described above.

Note that the term "legacy application" may seem a big rough as this application isn't terribly old, but Michael's definition of a legacy application is:

The main thing that distinguishes legacy code from non-legacy code is tests, or rather a lack of tests

However, I generally always use TDD where I can and when I don't have the pain of retrofitting it into existing code. I had the opportunity to do this the other day for a debugging utility that I had worked on. I am currently in the process of interfacing a legacy application with a new fancy Java based back-end application. The problem is that the new application is effectively still being developed, which means that the XML SOAP message we need to provide is constantly changing as the application evolves and bugs are removed.

To alleviate some of this pain, I built a little XML document manipulator into our interface application that would allow you to configurably manipulate the SOAP message by inserting, updating or deleting XML elements as required. I had initially built this right into the class that processes the message (I know - ugly!), but as the utility grew in functionality, I refactored it out into its own class and wrapped it in unit tests.

Being the typical lazy developer that I am, and as this was essentially a hack to help us with our real testing, I didn't actually test the new refactored class in the application, figuring that I could quickly fix any issues if and when they happened. No one seemed to be using this utility anyway, and I was feeling a little dejected because I thought it was pretty cool (it was fun to develop anyway) :-).

Anyway, Monday rolls around, its the last day of our sprint, and we have a demonstration to show at 2pm. Unfortunately the application had changed again, and we couldn't get any of our downloads to work. I became aware of the problem at about 1.30pm, and suggested that we use my "nifty" little utility to reformat the XML and get us through the demo. I was a little nervous that it hadn't really been used yet, but it was worth a try right?

Well, it worked first go! I was as stunned as everyone else. The unit tests had come to the rescue. Because of the unit tests, I had fixed many many problems while developing it and the end result was that it all worked correctly first go. Unit tests had saved our (especially my) bacon!

While I'm certainly not suggesting that we can forget about testing if we implement unit tests (actually, I still believe that while testing is boring, it is by far the most important part of the process), this example demonstrated to me again how important unit tests are.