Why Unit Test?


This morning a coworker introduced a team of programmers to unit testing in C# using NUnit and NMock, and I found good opportunity to muse over some of the implications of unit testing --- why it's something we absolutely must embrace. If you'll forgive the cliché, a funny thing happened to me on the way home...

The idea was to stop at a blood center along the way and make a blood donation. Normally this is a fairly painless process that takes 30-45 minutes. I was a little pressed for time, but the center was pretty empty and they said they'd be able to take a walk-in donation quickly.

Unfortunately, their laser printer chose that moment to wonk out and start eating donor forms. Two people were ahead of me in the line. The first guy got his form out, a bit wrinkled and missing a corner. The printer ate two more forms before finally spitting one out for the lady in front of me, who was doing an auto-donation, presumably for an upcoming surgery. Each time the machine jammed, the small group of technicians gathered there opened the printer's doors, removed the cartridge, pulled out shredded bits of paper, and assembled the machine, ever hopeful. Midway through eating my second form, the lady who'd been in front of me returned with her sheet, which, she'd just noticed, was imprinted with someone else's donor information.

There are a couple of things I took away from this. First, the ridiculous dependence we have on machinery for even the simplest tasks. This printer wasn't doing anything terribly clever: it was just filling out name, address, donor ID, and so forth on a pre-printed form. I don't think it prints a barcode or anything, though I may be remembering incorrectly. It would have taken one of the technicians only a minute to manually write this information on the form, though of course there may be a policy against this. But if the printer was that critical to processing donors, where was the backup (plan or printer)?

The second thing of note is that even though the printer was an off-the-shelf office model, it had found gainful employment in the field of medicine. Regardless of what quality standards the manufacturer may or may not have had in place, this device had been built into a system which ultimately handed a form with the wrong information to a donor. That's a fairly serious slip-up, even though it most likely would have been caught during the routine questioning of the donor, or on the donation couch itself.

I don't mean to criticize the blood center. These people do a wonderful job for the best of reasons, and they're very good at what they do. But the lesson is that there isn't always a good backup plan in place when technology fails, and we don't always know in advance where our technology will be used or how vital it may be to the larger system.

Much of the software I write is for the factory floor, with its countless safety hazards. Yet, it's also for safe travel, when it's used to build cars or jets or route luggage around an airport. It's for puffing up marshmallows and carbonating your soda and keeping machine screws out of your cereal. And it's for the medical industry, whenever it's used to manufacture medical equipment, or mix chemicals for the latest wonder-drug, or measure tolerances on a printer that will wind up in some blood center somewhere.

That's a lot of responsibility, and unit testing gives us one more tool to help assure that our code does what we expect it to. Having been exposed to such a tool, it would be irresponsible not to make good use of it. If features slip their release date, or if a sale is lost, isn't the possibility of higher quality still worth it?

NUnit started as a port of Java's JUnit, and is a toolset and application for running sets of tests on classes in isolation, making sure that the classes respond to stimuli with the correct method calls, return values, data sets, exceptions, etc. NMock is a tool for helping simulate the outside classes that the class under test interacts with; another for C# is DotNetMock (I don't know if these have any ancestry in Java's EasyMock). There's a lot to learn here, but a well-written start for .NET/Mono programmers may be found in Pragmatic Unit Testing in C# with NUnit. Java programmers have a version, too, Pragmatic Unit Testing in Java with JUnit. Both books are by Andrew Hunt and Dave Thomas, and both are very readable.

I'm sure as I start to incorporate unit testing into my C# and Java code I'll have more to say on the subject, but for now I'll just leave it at this: I'm sold. It sounds great in theory; I'll get back to you on the practice part.

Posted: Wed - January 26, 2005 at 10:08 PM          


©