Testing is awesome.

Many developers think that writing code is their job. That is not true. The job of the developer is to “Deliver working software frequently…” If you don’t test it, it isn’t working.

There is a limit to what can be reasonably tested, however. It is unreasonable to test what happens if SP1 isn’t applies to SQL Server. You can test for it, but it isn’t reasonable. It is reasonable to require that QA matches Production. Sometimes it doesn’t, though, and if you haven’t tested for that eventuality then you have a production failure.

In an attempt to make that limit of what can be tested as far away as possible, some opt for “Test Coverage.” Test coverage shows the number of members of the logic classes that are covered by unit tests. The instances are usually mocked to maintain atomiticity of the tests. The idea is that one test tests one method that has a single responsibility, and you can see right where your problems are.

Unit tests are a poor way to test software though. It is true that most errors are in the logic of a transactional system, but all of the rest of the potential problems - those related to system interaction - are utterly untested by unit tests.

In transactional systems, integration testing is where it is at. Unit tests are awesome for complex methods, but really you want to test is the integration between modules. If you happen to catch an error in one of the modules then fine, fix it of course. The integration test will catch those and the communication. The unit test will just catch errors in the module.

Wouldn’t you rather catch both? I would.

So why the focus on unit testing? A couple of reasons. First, you can legitimately design your software using the unit tests. It’s called Test Driven Development, and it is all the rage.

Don’t do it. If you need design, then design. Tests are for testing, not for design.

The second is for atomicity. Atomicity is testing one thing at a time. Awesome in theory. In practice, however, the line with the error turns yellow and has a big box next to it. Oh, don’t use an IDE? Sorry, you are too cool for me. You get what you deserve.

The third is laziness. Integration testing is hard. Sometimes, it is really hard, and takes as long to write as the code itself. Unit testing is usually fairly easy. It isn’t always easy - especially to write good unit tests. But most people don’t write good unit tests, and even bad integration tests are sorta hard to write. So, people write mediocre unit tests, and point to the TDD manifestos as a reason for being. Meh.

Remember what testing is for. It’s to make sure the software works.

Remember that “Working software is the primary measure of progress.” Code coverage isn’t. Number of unit tests isn’t.

Remember that saying “That error in production was one that wasn’t covered in my unit tests.” does not excuse the production outage.

Remember that the goal is to astonish the customers with software that does what they expect. They don’t care about your metrics. They care about working software.