$ cat "

Using Extension Methods to Refactor Your Tests

"

In a recent Katacast, Bobby Johnsson gave an excellent example of how C# extension methods can be used to create simplistic and readable test cases. He was performing the StringCalculator kata which is a kata where you write a calculator class that can calculate the sum of the integers in a given input string, for example "1,3,5".

Without extension methods an ordinary test case for this kata might look something like this:

[Test]
public void Add_GivenTwoSingleDigitNumbers_ShouldReturnTheSum()
{
var calculator = new StringCalculator();
int sum = calculator.Add("1,2");

Assert.AreEqual(3, sum);
}

This is a quite ordinary test, and there is no problem with the test itself. However if you have 15 other tests with the same structure there is room for some refactoring. One approach to refactor the test could be to simply create a helper method, like so:

private void VerifySum(string input, int expectedSum)
{
var calculator = new StringCalculator();
int actualSum = calculator.Add(input);

Assert.AreEqual(expectedSum, actualSum);
}

This would give a test case that look like this:

[Test]
public void Add_GivenTwoSingleDigitNumbers_ShouldReturnTheSum()
{
VerifySum("1,2", 3);
}

If you instead use the extension method refactoring you could create an extension method that looked something like this:

public static class StringExtensions
{
public static void ShouldAddUpTo(this string input, int expectedSum)
{
var calculator = new StringCalculator();

int actualSum = calculator.Add(input);

Assert.AreEqual(expectedSum, actualSum);
}
}

This approach gives a test that looks like this:

[Test]
public void Add_GivenTwoSingleDigitNumbers_ShouldReturnTheSum()
{
"1,2".ShouldAddUpTo(3);
}

I must say that the extension method approach gives a much more fluent and readable syntax, with a very Ruby-esque feeling to it. The back side of using extension methods is that it can be confusing for the reader, since you must have included the namespace of the extensions for them to show up, and you cannot resolve those namespaces as easily as you could with standard method calls. In my opinion, the example above is an excellent use of extension methods when the extension method is located in the same place as the tests, since that makes it obvious what is going on.

Extension methods is truly an awesome feature of C#, when used correctly.

Written by Erik Öjebo 2009-12-11 11:01

    Comments