Mark Needham

Thoughts on Software Development

Coding Dojo #7: Retlang/Hamcrest .NET attempt

with 4 comments

We ran a sort of coding dojo/playing around session which started with us looking at the .NET concurrency library, Retlang, and ended with an attempt to write Hamcrest style assertions in C#.

The Format

We had the same setup as for our normal coding dojos with two people at the keyboard although we didn’t rotate as aggressively as normal.

What We Learnt

  • We started off having a look at a concurrency problem in Cruise Control .NET which Dave Cameron recently fixed. The intention was to try and take one of the cases of multi threading and replace it with a message based approach using the Retlang library.
  • As I understand it, you can have any number of subscribers subscribe to any channel using Retlang which is different to the Erlang approach whereby only one subscriber would be allowed. A bit of experimentation also suggests that subscribers need to be subscribed to a channel at the time a message is published in order to receive it.
  • We started off with an initial test case but got sidetracked in trying to work out how to make the assertion syntax a bit nicer. The original assertion read like the examples on the website in that we check the state of a ManualResetEvent so that we know whether or not a message was received by a subscriber.

    The assertion read like this:

    var gotMessage = new ManualResetEvent(false);
    ...
    Assert.IsTrue(gotMessage.WaitOne(2000, false));

    We initially worked this to read like so:

    AssertThat(gotMessage, HasTrippedWithin(2.Seconds());

    AssertThat and HasTrippedWithin were local methods and Seconds was an extension method. It’s pretty nice but the problem is that we can’t reuse this code easily in other test classes and keep the readability.

    C# doesn’t have Java’s ability to import static methods so we would need to reference the class which the AssertThat method and HasTrippedWithin methods reside on directly either by having every test case extend it or by explicitly referencing it when we use the methods.

  • A bit more playing around with extension methods and trying to work out a good way to write Matchers led us to the following syntax:
    gotMessage.Should(Be.TrippedWithin(2.Seconds());

    We also considered putting a Verify extension method on object so that a test case could have a series of different matchers to be evaluated.

    this.Verify(
    	gotMessage.Is().TrippedWithin(2.Seconds())
    );

    For some reason we need to use the ‘this’ keyword in order to access an extension method defined on object – I don’t really understand why as I thought classes implicitly extended object, meaning the following should be possible:

    Verify(gotMessage.Is().TrippedWithin(2.Seconds()));
  • I think the way that our tests fail and the way that they report this failure is vital for getting the most out of TDD so I’d be interested to know of any ideas people have with regards to this. The thing that makes Hamcrest so good is not just the fluent syntax but the error messages that you receive when tests fail – it’s very clear where the problem lies when a test fails, there is rarely a need to get out the debugger in complete confusion as to why the test failed.

Next Time

  • I think we may make a return to coding some OO problems again next week – I’m not convinced that we are getting the most out of the Dojo sessions learning something which is new to the majority of people taking part.

Written by Mark Needham

January 22nd, 2009 at 11:02 pm

Posted in Coding Dojo

Tagged with

  • Dave Cameron

    You seemed to have understood better than I did what happened last night.

    So, the strength of hamcrest is really in the error messages? That makes me even more enthusiastic about trying some kind of namcrest library.

    I wasn’t sure if people were getting much out of the threading talk… I was surprised that people picked it up so quickly when it took me so long to trace the bugs down, but on the other hand I was disappointed that people weren’t contributing, kibbutzing, discussing as much as they might otherwise.

  • Neil Dunn

    I think the biggest take away from this kind of Dojo should be that it is very easy to get distracted and build the wrong solution…

  • http://www.markhneedham.com Mark Needham

    @Dave – yeh for me a lot of the benefit of Hamcrest is that if an assertion fails when the tests are running outside of the IDE it’s much easier to understand why there was a failure than if it’s a straight JUnit test failure for example.

    I think this is a combination of the matchers driving you towards writing better assertions as well as the usefulness of the error messages.

    I guess it was easier to understand the threading stuff because you whiteboarded it and were able to explain when there were questions.

    @Neil – yep, the yak was well and truly shaved in this Dojo!

  • http://blogs.claritycon.com/blogs/sean_devlin/default.aspx Sean Devlin

    @Mark – The reason you need to preface your Verify method with “this” is simply that extension methods require an object reference. This is because extension methods are basically just syntactic sugar. That is, the compiler will understand calls like this:

    this.Verify(predicate);

    to read like this:

    Verify(this, predicate);

    This is also why you can call an extension method on an null reference without getting a NullReferenceException (unless one is explicitly thrown from within the method).