Monday, February 11, 2008

Making a mockery of Testing

How much testing is enough testing?

If for example, you have to deliver a piece of software, some functionality and you have tight deadlines to meet, is 50% of code tested sufficient enough? How do you know that you have tested the most likely to fail 50% of the codebase?

That question probably sounds quite silly, but whenever I mention to people that they should be using Mock objects to test, they say that it is overkill, and that unit tests are enough. Further probing often reveals that these unit tests are really integration tests, tests such as ask for a particular record, or match filter to return records, and if records are returned, the test correctly passes.
That sort of a test is as brittle, weak and unknown a code fragment as the code fragment that it actually tests.

The database goes does, is that a code failure? Bet there's no test for the server actually going down, and if there was, how would you be able to descriminate between an infrastructure problem, and a coding error?

There are two approaches, one is to write tests, using MSTest, NUnit or whatever else you like to use, you pass a value, and expect a given response. This situation makes it incredibly difficult to test all of the code, since you have no way to control flow through a particular code branch. An example would be testing the exception handling block of a routine, given a unit test, there is no way to inject the exception into the code, so you're stuck with compiler switches to throw exceptions. Compiler switches is changing the code from what it will be in production to something else, which carries its own set of risks.

The alternative is Mocking. Now the concept behind mocking is that you create objects that are effectively proxies to the interfaces that a particular method or class uses. You then set expectations on those objects, and tell them to return data, which effectively drives the code through the desired execution path.
In that instance, if the database goes down, the tests will still pass, you are just driving the interface that is implemented at the data layer. You can't be touched, nobody can take that code down.

As a shortcut, to achieve that deadline, how much time would it take up to consistently and continually test and retest the code with such rigour?
Another question you will be asking yourself, is, is 50% tested code enough now, and will it actually take me less time to resolve all the bugs in the code using the debugger continually, instead of having repeatable and isolateable test targets to check instead?

Keep an eye out for a further article on how to do some mocking to enable the test coverage statistics to get up into the 90% area with nearly all classes.

No comments: