Monday, June 7, 2010

Testable Code Vs. OO code

Can we ever have a situation where the desire to have testable code is not 100% compatible with our Object Oriented Design? As i was working on some new code, i came across this issue and was happy to find that this is not a new issue as we see here. Even if you are not willing to accept the entire thesis, at the very least, we may want to use the thought of testing our code to drive some of our design decisions, since a robust, easy to run test suite is so important in software development, especially as projects grow in size and length and we can hardly remember what our code does anymore. An example of this in my project was my decision to implement the template method pattern where the template methods implemented by the child classes provide data back the parent class rather than invoke helper methods and provide greater functionality. This means that it is easier to test each new implementation and is less time consuming.

An additional aspect of this issue can be seen based on the book Clean Code, discussed in a previous post. While the focus there was on readability of the code, testability seems to overlap quite a bit with readability. The simpler we make our classes and our functions, the simpler for testing and finding the problems when test fail. Another aspect discussed at length there is the issue of parameters to function (or better yet, not having them). It is recommended instead to have members the contain the necessary data rather than pass it from function to function. (Beware, as this means your classes will not be thread-safe and will require a new instance for each use). From what i recall (not having access to this book right now), the main issue was readability, but here too, another fringe benefit is testability, especially if you are using TestNG (or JUnit 4). The reason for this, you create this class and populate the member data correctly and then can run tests repeatedly with little typing other than the method names. Writing and running the tests is now easier since you need not figure out all the parameters of a given function. Also, running multiple tests with different data (using TestNG DataProvider) is easier to provide.

There are two other ways that testability impacts design in my current project:
The first is in using interfaces even when i have no plans to implement another implementation of a member class. It is much easier to mock behavior and isolate a test if we use interfaces and then plug in a simpler implementation of our interface for test purposes. Of course, use of Spring here and the Spring application context makes this trivial

The second aspect is in determining the scope of functions in order to enable testing of private functions as discussed here. I agree wholeheartedly with Bob Lee in his post that your code will be better if private functions are tested individually and you do not leave all your testing to the public API.

I realize that much of what i write here is well known but i see that many of my peers are still not recognizing how important repeatable tests are. It is hard to see down the line when you are creating a new project from scratch. But, there are two ultra important reasons that we need to have a repeatable test suite. The first is documentation. As written about in Clean Code, Javadocs are not reliable. It happens too often in projects that programmers do not make sure to update javadocs as things change, and this is true for comments as well. The best documentation in addition to well written code with good naming (as discussed in my previous post about the book Clean Code), is the tests of the API, that show exactly how a function was meant to be used by the original author. It enables us to also what results it was meant to return and all error cases. The more tests on a function the more information provided. The second reason is maintainability. As our software has gotten larger/bloated, while staff has been pared down, a rewrite of our software is not truly possible. The confidence to make changes stems from good, repeatable tests.

A second part of the confidence to make changes in a larger project comes from a good regression suite, which i hope to discuss in an upcoming post.

No comments:

Post a Comment