Thursday, July 23, 2009

Real programmers write unit tests (part 3)

Ok, you know the drill: you have to modify a feature of Program X and to do this you have to modify a class – lets call it UglyThing – and this class is a mess and it has no unit tests. This class has Efferent coupling through the roof and large methods that are really difficult to understand and work with. It feels like you are going to have to build the whole application by hand just to set things up for unit testing this class. What is a pragmatic programmer to do ?
In my situation at work I don't have any choice because the development process requires me to have unit tests for new or modified code. In a more permissive environment I might be tempting to skip the unit tests. However, if the code really is that bad skipping unit tests is really not a good idea.
Of course the first thing to do is to analyze the code carefully. In the context of a commercial application you really have to be cautious about any modifications you make to the code. Yet, sometimes a few well chosen simple and safe modifications can do the trick. Other times, techniques like Introduce middle man may be required. In more extreme cases you may have to turn to other techniques.

Extract static method


In OO programming adding static methods normally is something that you want to minimize. However, if you have reviewed the code and have been unable to find more conventional ways to modify the class to add unit test in the context of your current project compromise are in order. This may be a case where using static methods could help. In practice I see different variations on this theme:
Sometimes a class has one central method that does all the work and that could have been static from the start. In Java I extract the body of this large method to a static method with package visibility. I use the minimum visibility required to write unit tests for this in another class in the same namespace (Java package). Sometimes one has to add some of parameters to make this work. Often more parameters than the maximum that I would normally recommend. However, since this method is not part of the public API of the class I think this is an acceptable compromise. The last step is to replace the original code by a call to the static method. Now you can write a bunch of unit tests (possibly using parametric tests) for this method (the static version). It is now safe to perform actual functional modifications to the code for your new feature.
In some other cases it is not possible to extract whole methods and one has to limit the extracted code to portions of the original code. Even this will often be sufficient to add an adequate level of unit tests and proceed safely with the functional modifications.

Parting comments


Next time I will talk about the Layers architectural pattern. A layered design is a great way to set the stage for unit tests in some situation where unit tests are sometimes difficult to implement.

Wednesday, July 8, 2009

Real programmers write unit tests (part 2)

In this post I will discuss some of the techniques that I use to work with external libraries and legacy code.
At this point I'm still experimenting with this. However, all of the techniques that I will discuss here have been very useful in several cases. All of the techniques that I have used require to make some compromise
about the simplicity or sometimes what I would call the OO purity of the code. However, in all the situations where I have used those techniques the gains were worth the sacrifices.
But first we need to talk a little bit more about the setup for the tests.

Test setup


Since writing unit tests adds a good number of files to the source directories we decided to put our test code under a different base directory than the one used for the tested code. Because of Java's visibility rules we use the same package (namespace) for a test class than for the class that we are testing. Thus, our test code directory structure mirrors that of the tested code. We put the test code under Test and the tested code under Src. This makes it easier to process the files separately as part of our daily Ant build (run unit tests, metrics and other Ant tasks).

Unit test best practices


I will not cover all the unit tests best practices here. If you want more information about that just read JUnit best practices at http://www.javaworld.com/jw-12-2000/jw-1221-junit.html . Since several unit test tools (Nunit, DUnit) are ports of Junit those best practices apply on any platform or language with little modifications. C# programmers might want to read NUnit best practices at http://scottwhite.blogspot.com/2008/05/nunit-best-practices.html . Make sure you read the comments.

The recipes


I will use names inspired by the names used for refactorings in Marin Fowler's Refactoring for my recipes.

Introduce middle man


Normally if a class doesn't do much you want to remove it. For example, if a class just delegates calls to a member. The refactoring for this is called Remove middle man.
For unit testing involving legacy or third party libraries it can sometimes be useful to introduce such a class. I call this Introduce middle man.
For example, in my last project I decided to create an ErrorHandler class. I needed to be able to implement an error handling logic that was a little more elaborate than usual. One thing that this class had to do was to interact with an OPC UA Session object. Now building an OPC UA Session object is not easy. It requires a bunch of other code and because the Session class does not implement any simple abstract interface that I could use I was in a difficult position to write unit tests for my ErrorHandler class. Fortunately, my code only called one Session class method (Reconnect) so in order to write good unit tests I decided to introduce a middle man. I chose to create an Interface ISessionConnector with one method: Reconnect. Then I created a class than just delegated the call in the Src branch and created an implementation in the Test code branch that allowed me to simulate different scenarios (reconnection failure or success). I was able to get 100% test coverage of my new class. Another advantage of this approach is that I don't actually have to get an OPC UA server running in order to run this test. Good judgment is essential here. You should watch for middle man that gets too complicated. You might end up not testing the right code. If the middle man remains simple this works well. In my case, middle mans have often allowed me to test several classes that would have been difficult to test otherwise in legacy code or code that used third party libraries.

Parting comments


Some people might wonder why I don't use mock libraries like Jmock or others. The reason is simple: none of the mock libraries work the way I want. I plan to use mock libraries in the future but probably not exclusively.
Next time I will talked about another unit testing trick to handle legacy code: Extract static method.

Monday, July 6, 2009

Real programmers write unit tests (part 1)

Among the good practices that we have put in place at work the one that has been consistently rated the most beneficial by the programmers using it is writing unit tests. It has a beneficial impact on both the quality of the code, the number of bugs detected in the system tests and the schedule. Unit tests make development more deterministic and less stressful.

The tools


We write most of our code in Java so we use JUnit. We use version 1.4 and we use the Hamcrest matchers. We also use a few extensions:

  • Fest for testing GUI

  • DbUnit for testing database related code.

  • We do not yet use mock libraries. Because we write a lot of mathematical algorithm, the Junit 1.4 parametric tests is a great tool for us. It is very productive.
    We use Ant to run the unit tests as part of the daily build. The build is interrupted if there is a test failure. No release image is generated if a unit test fails.
    Recently I did some development in C#. I used NUnit for unit tests on that project.

    The process


    We do not yet use TDD but we do test early. Also, for me, the emphasis as shifted recently from testing methods to testing scenarios. I will probably keep using a mix of method oriented and scenario oriented tests because I find both type to be useful. Method oriented tests for simple more technical classes and scenario oriented tests for the more complex business related classes. The details of the process depends on the type of development involved: maintenance of legacy applications and development of new applications and modules use a slightly different approach.
    Development of new application and modules gets the most benefit from unit tests. It is easier to apply good design and coding practices with new code and those facilitate unit testing. Design principles and coding practices that are beneficial to unit tests includes:


  • Small highly cohesive classes

  • Those are easier to unit test

  • Defining interfaces and coding to them

  • This makes unit testing easier because it facilitates writing mock classes and stubs. I mentioned earlier that we do not yet use mock libraries. However, we do write mock classes. Having well defined interfaces makes this process easier.

  • Loose coupling

  • Keeping an eye on coupling is really important. I use a metrics tool for that and I refactor early if needed. High Efferent coupling can make unit tests very difficult.


    Even on new projects you will sometimes have to work with code that was not developed with unit tests in mind. For example, third party libraries and classes can be a source of complications. In my next post I will talk about writing unit tests in more details. I will show some techniques that you can use when working with non unit tests friendly code and legacy applications.