Home > Testability > Design for Testability

Design for Testability

April 20th, 2010

A car that cannot be tested is a Toyota. We all know that a car needs wheels and a motor to drive. However when engineers build a car they do not just include the bare functionality, they’ll include certain features just for the purpose of testability. Being able to test all functionality is a feature in itself and must not be omitted.

When designing classes it is just the same: some API features are just there for the purpose of testability. It is good design and not an ugly hack if you include certain features just for the purpose of testability!

Let’s consider a Dice class

public interface Dice {
    public int roll();
}

This dice rolls random numbers only. Toyota might consider this a feature-complete dice. We know better. A random dice cannot be used to test software!

Rather we should implement the Dice class as follows

public interface Dice {
    public int roll();
    public void stage(int... n);
}

So then what if we implement two subclasses RandomDice and ScriptableDice and add #stage to the scriptable dice? This won’t work since we want use the same code for both playing an actual game of Ludo and for testing the game. In particular if you’re using a Dependency Injection framework such as Spring or Guice, as it common practice these days, it is a necessity to have a common superclass that works for all setups! Hence, the #stage must be in the superclass. The implementation of RandomDice will throw an UnsupportedOperation exception with the message for testing only; the scriptable dice, of course, will script it self with staged results.

It is good practice though to document code that is used for testing only. We can either do this with a comment or with an annotation. It is preferable to use an annotation since annotations are machine readable while comments are not.

Thus we define

public @interface ForTestingOnly {  }

And rewrite the Dice class as follows

public interface Dice {
    public int roll();
    @ForTestingOnly public void stage(int... n);
}

Now we got a testable and well-documented dice class.

Happy hacking!

akuhn Testability

  1. No comments yet.
  1. No trackbacks yet.