Sunday, January 18, 2009

On testing data objects, the first step towards TDD

On testing data objects, the first step towards TDD

The simplest class behavior to test is the basic mapping of an object's properties either through it's constructors or through it's accessors. This translates to validating the correctness of the object creation, or validating the correctness of the object's modification.

Validating object construction

The first and easiest test cases involve the construction of an object. Usually the first test case involves validating and object's default values through a default constructor. Remember to question what an accessor should return if an object field is null.

Subsequent tests involve and validate that the construction parameters are correctly represented through the objects accessors.

I encourage validating a single object property per test. This makes it easier to identify what code is at fault when a test fails, it also facilitates defining test names which describe the expected result of the test.

Validating object modification

The next step in object testing, may well be the modification of properties. I am personally of the opinion that this should cause us to question our object modeling, but there are some valid uses for this, see bellow.

These tests involve constructing an object with one set of values, and validating that modification to that truely re-assigns the value. It is important to use test data that clearly demonstrates the modification of the field. So if the initial value is the value '1', the modification should assign '2'.

There is little interest in validating multiple subsequent modifications on a specific object instance unless the object supports some special caching or history behavior. In most cases and assignment is an assignment is an assignment. Dont clutter your tests with sequential validations.

Why validate the obvious case?

In the javabean and pre-version 3.0 C# approach to properties, an accessor is an explicit block of code. Consequently, it can contain bugs. This is rarely the case, but it does happen from time to time. Usually such bugs are quickly identified and fixed, and subsequently not repeated, but there are nonetheless reasons to validate them.

Remember that even if the property uses the trivial implementation, it remains a kind of method. Even C#'s properties are a kind of field-separated accessor with a signature that remains independent of the internal class data representation. This means that through the magic of refactoring, changes to the underlying structure of a class can continue to expose identical properties even if the origin of said properties has changed. Wouldnt it be nice if we could validate that a refactoring of a class' internal workings continued to provide the same external behavior? I certainly think so.

In C# 3.0, it is now possible to specify a property with a short-hand notation which automatically generates the trivial implementation. This does not invalidate my previous argument. The short-form syntax can be replaced with an elaborate evaluation logic without changing the class' signature. A simple test could help to catch a sudden change in behavior. Remember that tests are a kind of code-level contract. Changes in class behavior are a change in contract that must be re-negotiated by the programmer for all the affected parties including the test code.

How far should we go with testing the trivial implementation? Not very far. The tests are just a safe-guard against obvious violations, and the number of tests should reflect the complexity of the tested code. Only if the underling code grows in complexity, should the tests grow in number.

What about encapsulation?

Let me underline that this discussion focuses on data objects. Objects who's primary function is to store and transport data. Though there are reasons and contexts in which the are appropriate, and others in which they can be avoided, they remain the most frequent type of object that I've seen in application code bases. Regardless of your opinion on object modeling, they remain the easiest kind of object to test, and so for a TDD newbie, they are the low-hanging fruit.

Conclusion

Data objects are easy to test. The simplicity of their implementations make them an ideal starting point for test-driven development newbies. Start by validating object construction, then move on to object modification.

Thursday, November 27, 2008

greetings

Hi all, this is a short message to welcome you to the code reef blog. This blog will hopefully grow from my musings and comments on the developing of software, the software user, and everything in between.

Why "the code reef"? though I am not a diver, I find the allusion to be an imagination inspiring one. I am reminded of nature shows I watched as a youngster. Shows where divers would swim through reefs around the world and show us the beautiful schools of fish that inhabited the reef, the complex ecosystem of living creatures, some cohabiting peacefully or symbiotically, others preying on those lower in the food chain. Many potentially fatal dangers lurk hidden in these reefs as well.

I am also reminded that the the ecosystem of a reef is a fragile one, easily unbalance and destroyed by external factors. Pollution, natural disasters, violent weather patterns, and sometime a simple imbalance in the natural order of things can all contribute to the unfortunate end to the beauty and promise that once was.

In short, I find the comparison fitting - much of what I have said about the ecosystem of reefs, could also be used to describe the industry in which I work, the projects I have been involved in, and the teams and technologies I have worked with.

I love software development most of the time, I hate it others, but I can safely say that I learn something new every day. Hopefully some of the more interesting morsels will find their way into these posts.