Beyond unit tests

One of the main goals of this book is to help people move beyond unit tests. However, please understand that this is not a book against unit testing. Unit testing is an incredibly useful practice and I am not trying to make a case against it. However, it has become a victim of its own success. Because NUnit and similar tools are now so ubiquitous, they get abused by being used for component and integration tests or even for acceptance testing. These tools were never designed for such tasks. The role of tests has evolved from verifying functionality to guiding development, and for this we need a completely different set of tools. Useful as they are, unit tests are often not enough.

Back in 2002 I worked on configuration management software. That beast had more edge cases than anything I had seen before. The whole team wasted enormous effort on manual verification. About the time that we started to rewrite the engine in Java, I read about JUnit, which came like a gift from heaven. We automated most of the dull verification tasks. Problems became smaller and we were no longer wrestling with big issues that required several days to diagnose.

A few months later, I could no longer understand how I ever managed to work without unit testing. Putting requirements into tests turned out to be a great way to make sure we all agreed on the targets, and provided us with guidelines on how to hit them. Tests provided an early sanity check for our APIs. JUnit was magic.

Our software was used by sales teams in several large electrical equipment manufacturers. The software provided the ability to instantly validate any configuration — for example, a particular motor with a particular power supply. It also automatically provided a price quote, a delivery proposal, and a bill-of-materials list. Rules for an average product took about a month to model and probably about two more months to test and clean up. Hierarchical dependencies and connections made the models very error-prone. People from the modelling department were really not at ease with making any changes after the initial version was approved. We solved this issue in our code, so we thought that we could do the same for the models. We developed a glue between JUnit and configuration models, which would theoretically allow someone to write and automate tests for models. This practice never advanced from a proof-of-concept stage. Configuration modellers did not know Java, did not want to know it, and could not be bothered to work in an IDE. They could not read JUnit tests nor understand what went wrong if something failed.

Step by step, I started to see other limitations of unit tests. The target we set with JUnit was our vision of the goals, which was not necessarily the same as the client's vision, and there was absolutely no way we could get clients to read and verify the tests. JUnit was great for small pieces of code, but quite cumbersome when external systems were involved, especially when there was work to be done in the database. Knowing what I know now, I really wish I had had FitNesse in mid-2003.