# Friday, February 13, 2009

In my Zero-Friction TDD series, I focus on establishing a set of good habits that can potentially make you more productive while writing tests TDD style. While being able to quickly write good tests is important, this is not the only quality on which you should focus.

Maintainability, not only of your production code, but also of your test code, is important, and the DRY principle is just as applicable here.

Consider a test like this:

[TestMethod]
public void SomeTestUsingConstructorToCreateSut()
{
    // Fixture setup
    MyClass sut = new MyClass();
    // Exercise system
    // ...
    // Verify outcome
    // ...
    // Teardown
}

Such a test represents an anti-pattern you can easily fall victim to. The main item of interest here is that I create the SUT using its constructor. You could say that I have hard-coded this particular constructor usage into my test.

This is not a problem if there's only one test of MyClass, but once you have many, this starts to become a drag on your ability to refactor your code.

Imagine that you want to change the constructor of MyClass from the default constructor to one that takes a dependency, like this:

public MyClass(IMyInterface dependency)

If you have many (in this case, not three, but dozens) tests using the default constructor, this simple change will force you to visit all these tests and modify them to be able to compile again.

If, instead, we use a factory to create the SUT in each test, there's a single place where we can go and update the creation logic.

[TestMethod]
public void SomeTestUsingFactoryToCreateSut()
{
    // Fixture setup
    MyClass sut = MyClassFactory.Create();
    // Exercise system
    // ...
    // Verify outcome
    // ...
    // Teardown
}

The MyClassFactory class is a test-specific helper class (more formally, it's part of our SUT API Encapsulation) that is part of the unit test project. Using this factory, we only need to modify the Create method to implement the constructor change.

internal static MyClass Create()
{
    IMyInterface fake = new FakeMyInterface();
    return new MyClass(fake);
}

Instead of having to modify many individual tests to support the signature change of the constructor, there's now one central place where we can go and do that. This pattern supports refactoring much better, so consider making this a habit of yours.

One exception to this rule concerns tests that explicitly deal with the constructor, such as this one:

[ExpectedException(typeof(ArgumentNullException))]
[TestMethod]
public void CreateWithNullMyInterfaceWillThrow()
{
    // Fixture setup
    IMyInterface nullMyInterface = null;
    // Exercise system
    new MyClass(nullMyInterface);
    // Verify outcome (expected exception)
    // Teardown
}

In a case like this, where you explicitly want to deal with the constructor in an anomalous way, I consider it reasonable to deviate from the rule of using a factory to create the SUT. Although this may result in a need to fix the SUT creation logic in more than one place, instead of only in the factory itself, it's likely to be constrained to a few places instead of dozens or more, since normally, you will only have a handful of these explicit constructor tests.

Compared to my Zero-Friction TDD tips and tricks, this particular advice has the potential to marginally slow you down. However, this investments pays off when you want to refactor your SUT's constructor, and remember that you can always just write the call to the factory and move on without implementing it right away.

posted on Friday, February 13, 2009 8:56:21 AM (Romance Standard Time, UTC+01:00)  #    Comments [4] Trackback
# Wednesday, January 28, 2009

As readers of my old MSDN blog will know, ploeh blog is moving to this new site.

Responding to the current financial crisis, Microsoft is cutting costs and laying off 1400 employees. During that process, the entire Microsoft Dynamics Mobile Team is being disbanded, which is very sad, since it was a very nice place to work. The team spirit was great, and we were really committed to agile development methodologies, but all good things must end...

Currently, I can't even begin to guess what the future looks like for me, although to regular readers of my blog I can state that I sincerely intend to keep writing as I always have. If you subscribed to my old blog, then please subscribe here instead. The blog is moving because the old blog belongs to Microsoft, and only employees can post, so I'll soon be writing my last post on the old blog.

Until now, it's always been Microsoft's policy to retain the old blogs, even when the original authors leave the company, so while I will not be able to post to the old blog, I expect the old posts to be around for a long time yet.

Professionally, I don't know what I will do now. If I can find new employment in these times, I may simply decide to take on new challenges with a new employer. However, I'm also considering free-lancing for a while: Coding, mentoring, lecturing, writing...

If you are in the position where you think you can use my services, whether for full-time employment or just a few days, please let me know. Keep in mind that I'm based in Copenhagen, Denmark, and while I can certainly travel after work, I cannot permanently move due to family obligations.

posted on Wednesday, January 28, 2009 10:03:29 AM (Romance Standard Time, UTC+01:00)  #    Comments [3] Trackback