Wafer thin testing?

I’ve spent the past month or so helping a corporate client improve code quality in a sprawling application. It’s non-trivial, the code-base is huge, the quality is, at best, questionable and the coupling is excessive and made worse by the fact that much of the system is coupled together using a single huge blob of relatively unstructured XML. Fun, fun, fun…

As with the refactoring project, the first tests have taken some time to build. The release cycle of this project is as far from that of the refactoring project as is possible; where the refactoring project often released multiple times per week this project requires weeks of monkey testing and multiple levels of sign-off to get changes into production. This slow pulse is currently my biggest cause for concern; we need to make some bold moves to get tests in at the narrowest inflection points so that we can start to make headway but doing so requires potentially dangerous changes and, ideally, these would be followed by a swift test and release cycle so that we find out sooner rather than later if we’ve broken anything whilst getting the code to a point where unit-testing is possible.

The last few days have seen us making better headway, we’ve used a similar approach to the one I used when adding the first FX tests to the refactoring project. Slip in an interface or two to decouple the code you need to test from the concrete classes that it’s coupled to. Build a test harness that links with just the code you need to test, mock up service providers to implement the interfaces that we’ve added, build instrumented wrappers for the real service providers so that we can save down test data and then use the mocks to serve up the canned data so that we can build repeatable tests for a body of code that usually relies on masses of external connectivity and data that ticks as markets shift.

The granularity of the first tests was too great to be able to move quickly; so once they were in place the first thing to do was to break out the lower level code that we wanted to test and use the initial tests to make sure we hadn’t changed any behaviour. Once the class under test had become two classes under test we could write more fine grained tests and step up the pace.

Most of this was done using pair-programming; one of us to introduce tests to the code as quickly as possible and one who knew the existing code and knew how the system hung together. This worked well and now we have a fairly comprehensive set of mock objects and instrumentation, and a few tests. The next step is to fill out the tests and refactor the code as required to remove some of the ‘fluff’, make the code simpler and easier to understand.

We’ve even managed to reduce the surface area of the blob of XML phlegm that infects this particular piece of code. The fact that the previous refactoring release had removed much of the ‘unwrapped Dom’ access from the code and pushed it through a wrapper object helped greatly with this. We simply instrumented the Dom wrapper, examined the xpaths that were being used and build our blob so that it only contained what these tests required…

Still a long, long, way to go; but we’re moving in the right direction.