Editorials

Unit Testing Standards

I’ve taken on the task of overseeing the development of Unit Test standards for a group in which I’m a part. So, I thought I might use this opportunity to share some thoughts, and hopefully get some feedback from others. So let me start with some philosophical things to get the conversation started.

I have practiced Test Driven Development, and really like that methodology. I have seen it taken to extremes in ways that I don’t feel provide value. For example, when being mentored in the practice, we started out with a simple class. Before we could create a property with a setter or getter we first had to create a unit test for those properties. I really felt that was a waste of time the majority of the time. If you are creating a property that is exposed, and has both a setter and a getter, then all your unit test is doing is confirming that the compiler for your language works. Although I like and practice TDD, I’m not sure it should be a requirement (sorry Uncle Bob).

Testing your properties becomes more meaningful in object oriented languages where you implement encapsulation, or have immutable properties. At that point, real work is being done, and business logic, or something more meaningful is being performed, and a unit test provides value at that point. Most diligent object oriented programmers don’t like exposed properties. They reveal too much about the underlying architecture of the program. Rather than having an oven object that exposes a temperature property, they prefer an oven object that raises an event when the temperature changes. This way the client doesn’t constantly poll the oven object for the current temperature. The client knows what the temperature is because the oven tells the client when the temperature changes.

I have worked with folks wanting to have as close to 100% code coverage in their testing. I’m not sure what drives that measurement as a goal other than the fact that it can be measured. If you have 100% code coverage, then there shouldn’t be any holes. But how much time or money did you spend getting that coverage.

I do think it is important to separate the concept of integration tests from unit tests. For example, if you are building a consumer of data from Entity Framework, and create a mock for the Entity Framework call, then you have a unit test. However, if you are testing an Entity Framework implementation that calls a database, you have an integration test. In short, a unit test can stand alone without any external dependency. A unit test isn’t better; it is just different.

In distinction from the previous example about Entity Framework, what do you do when you are creating unit tests for SQL Functions or Stored Procedures? If you can mock the sources being used for those tests, either by creating new data or having baseline test data that doesn’t change, then you would have a unit test. If the supporting baseline data changes, you could have the same test code, but, theoretically, I think I would call that an integration test. Maybe that’s a distinction that doesn’t need to be called out.

So, if you don’t do 100% code coverage, then how do you know when you’re done? Or in more simple terms, how do you determine what to test? The short answer for me, as a starting point, is to test things for which you have created logic. Here is an example to provide some clarification.

internal bool IsModFour(int number)
{
    return number % 4 == 0;
}

This method simply returns what the compiler directs. Yes, you could put a unit test on it, because someone could have typed number % 4 != 4; What really is the risk here?

However, if we combine two different things in the method, the logic becomes more complex, and a unit test is more meaningful of purpose.

internal bool IsModFour(int number)
{
    return number %2 != 0 && number % 4 == 0;
}

Granted, this second method is still only confirming what the complier generates, as all methods do I suppose. I do see a difference in the risk potential. I’m combining two different concepts into a single logical result, and the risk increases. Again, maybe I’m splitting hairs here once again.

Well, those are some high level thoughts to get a discussion going. I’m looking forward to, and hoping for some comments from you all (some USA southern slang there).

Cheers,

Ben