Thursday, January 29, 2009

Test Utilities using extension methods

So, I was working with Jeff McWherter on some TDD stuff in C# today, and I came upon a trick that I really like. When I used to do C#, I was working in the 2.0 version of the .net framework. This meant that, while I had cool things like generics and anonymous methods to help me out, I didn't have extension methods. Well, Jeff and I were working in .net 3.0, so I had the benefits.

We were writing some tests that need a couple instances of a data object. Well, my first test new-ed up the instance and added it to the collection. This instance needed to have the due date property set, so I did something like this:



Well, there's a bit of annoying duplication there, so I changed it to:



with a method later on that looks like this



Okay, a bit better.

A little bit later, we had another test fixture that used the data object in a similar way, so I was looking for a way to bring the thing() method into a scope that was available for the other fixture, as well. When I was doing 2.0, I would have probably built a base class for my test fixtures and subclasses it in both fixtures. Yuk! Those who know me know that I have a special, black, cold place in my heart for subclassing like this.

Enter extension methods


I want a way to have some utility methods that I can use whenever I have a fixture that needs to build things. Aha! Let's make an interface:

public interface TestsThings {}

And, add an extension method to it:



Cool. Now, my test fixtures can implement TestsThings and get the method, so the construction of the lists will now look like this:



Unnecessary Construction Parameters? Yuk!



Well, not happy to leave a bad thing bad, I decided to take it one step further. I want to be able to write



How to do that? Hmm.... Ah, here we go. Let's change ThingTestingUtilities to look like this:



Works much better. But, there is still a matter of duplication in the DateTime.Now... stuff. So, let's take this a step further. What if I could write this:


That looks much better. Yeah, if I was in a different language, I'd do something like:
this.NewThings().WithAnOffsetDueDate(1.days);
[Update: Steven Harman alerted me that you can do this. I'm too lazy right now to implement it, though. Maybe later]
[Update2: Leon Gersin added a comment showing how to extend it like 1.days. Check it out.]

So, let's add a helper method. The utility class looks like this now:



Cool, compiles, runs, now my construction looks like this:



Extension methods can definitely help do some neat stuff. I don't have to subclass, I can add methods by simply implementing an interface. This also gives me the ability to create interfaces that are focused on different tasks that my test fixtures might need, so I don't have to load up subclasses with unnecessary mixes of unrelated methods.