Tuesday, November 24, 2009

The joy of MSpec

I’ve just kicked off a new MVC Framework application today. I’ve been considering moving to more behaviour based testing for a while now and I’ve been intrigued by Aaron Jensen’s descriptions of his MSpec (Machine Specifications) framework. So this afternoon I downloaded the build from here and got coding (just click ‘login as guest’ at the bottom).

It’s very nice. Here’s some tests for my container setup:

using System.Web.Mvc;
using Castle.Windsor;
using Machine.Specifications;
using Spark.Web.Mvc;
using Mike.Portslade.Web.IoC;

namespace Mike.Portslade.Web.Tests.IoC.ContainerManagerSpecs
{
    public class when_container_is_created
    {
        Because of = () =>
            container = ContainerManager.CreateContainer();

        It should_register_HomeController = () =>
            container.Kernel.HasComponent("homecontroller");

        It should_register_SparkViewFactory = () =>
            container.Kernel.HasComponent(typeof (SparkViewFactory));

        It should_register_an_IControllerFactory = () =>
            container.Kernel.HasComponent(typeof (IControllerFactory));

        private static IWindsorContainer container;
    }
}

I love the readability of the test code. Sure you have to learn to love the ‘=()=>’, but come on people, lambda syntax is hardly new any more.

When I run this using TestDriven.NET, my test runner of choice for many years now, I get this output:

when container is created
» should register HomeController
» should register SparkViewFactory
» should register an IControllerFactory

The only thing I don’t like is that the ‘It’ has gone missing which is a shame, otherwise this is just what I want from behaviour based testing framework; very low friction and easy to read output.

Well done Aaron, I’m very impressed.

Sunday, November 22, 2009

Make working with open source a breeze with Hornget

If you’ve spent any time working with open source .NET projects like Castle or NHibernate you’ll know the pain of building them from source. At first it seems very easy, you just get the source code from the repository and run the build.bat file or whatever. Any good OS project should just compile into a convenient build directory from which you can grab the assemblies you want.

The pain starts when you have several OS frameworks you are using that have dependencies on each other. Castle and NHibernate are the classic example here. Castle has a dependency on NHibernate and NHibernate has a dependency on Castle. I used to have to go through a complex build-copy-rebuild dance to get the two trunks to work with each other. These days I use a whole suite of open source tools:

Castle
NHibernate
Fluent-NHibernate
Log4net
MassTransit
MvcContrib
Automapper
Spark View Engine

And there are probably others I’ve forgotten. Getting all these from trunk and building them is a major headache.

If you’ve ever played with a Linux distribution, the really cool thing you’ll notice about it compared with the Windows world, is that you can get any software you need by typing (on Ubuntu for example)

apt-get install myFavoriteSoftware

It downloads and installs it on your system along with any dependencies. It’s quite amazing that Windows doesn’t have this yet.

But now this awesomeness is available for open source .NET projects and is supplied by Hornget. Hornget is the work of several members of the Scottish ALT.NET group, most prominently Paul Cowan. All you have to do once it’s downloaded and built (instructions here) is type:

horn –install:nhibernate

Horn will update your local nhibernate source and all its dependencies and then build them in the correct order, copying the dependent assemblies into the correct places for the next build. It uses a Boo based DSL to configure the packages and many of the most important .NET OS projects are represented. I imagine that anyone with a serious .NET OS project is going to want to be included. It’s on my todo list to create a package description for Suteki Shop :)

The list of supported packages is here.

I just had a couple of hiccups getting it working. The first was that I didn’t have Git installed. Git is distributed source control from Linus himself. You can get a windows version from here. You want the ‘Git-1.6.5.1-preview20091022.exe ’ or whatever is latest. I couldn’t use the default Git protocol from work because our firewall blocks the Git ports. There is a work around, but for the time being I’m just using horn from home.

The second irritation was Powershell. Rhino tools, which many other projects have a dependency on uses Psake, the powershell build tool. You have to tell powershell to allow script execution by typing:

set-executionpolicy remotesigned

I was totally confused when after doing this, it still wouldn’t run Psake. It turned out that it was because I’m working on 64 bit 2008 R2 and typed set-execution policy in the 64 bit powershell. The Psake script gets run under x86 powershell which has a separate configuration. After I set the execution policy in the x86 powershell prompt, it all worked. Thanks to Steve Mason for pointing that out on the Hornget group.

Sunday, November 15, 2009

Fun with Linq Aggregate

Say we’ve got a CSV file:

private const string csv = 
@"1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
16,17,18,19,20";

We want to parse it into nested List<int>, and then print out all the numbers on a single line. We might do it like this:

public void ParseCsvAndOutputAsString()
{
    var data = new List<List<int>>();

    foreach (var line in csv.Split('\n'))
    {
        var innerList = new List<int>();
        foreach (var item in line.Split(','))
        {
            innerList.Add(int.Parse(item));
        }
        data.Add(innerList);
    }

    string output = "";
    foreach (var innerList in data)
    {
        foreach (var item in innerList)
        {
            output = string.Format("{0} {1}", output, item);
        }
    }

    Console.WriteLine(output);
}

Yes, I know I should use a StringBuilder and AddRange, but ignore that for the moment, I’m trying to make a point here.

Taking a collection of values and reducing them down to a single value is a very common task in programming. Here we’re doing it twice; first we’re taking a string, splitting it apart and then reducing it down to a single reference to a List<List<int>>; then we’re taking the may items of data and reducing them to a string.

This is so common in fact, that many programming languages have some kind of ‘reduce’ functionality built in. It’s especially common with functional languages. Did you know that C# also has a reduce function? It’s the Aggregate extension method. Here’s the same method written in two statements with it:

[Test]
public void ParseCsvAndOutputAsStringUsingAgregate()
{
    var data = csv
        .Split('\n')
        .Aggregate(
            new List<List<int>>(),
            (list, line) => list.Append(line
                .Split(',')
                .Select(str => int.Parse(str))
                .Aggregate(
                    new List<int>(),
                    (innerList, item) => innerList.Append(item))));

    Console.WriteLine(data
        .SelectMany(innerList => innerList)
        .Aggregate("", (output, item) => string.Format("{0} {1}", output, item)));
}

Aggregate takes two parameters; the first sets up the initial value, in our case we create new instances of List<List<int>>, List<int> and an empty string, this is known as the ‘accumulator’; the second is the function that does the accumulating.

Aggregate works really well with fluent interfaces, where methods return their instance. I’ve added a fluent ‘Append’ extension method to List<int> to help me here:

public static List<T> Append<T>(this List<T> list, T item)
{
    list.Add(item);
    return list;
}

So any time you’ve got a collection of stuff that you want to ‘reduce’ to a single item, remember Aggregate.