Friday, February 11, 2011

Announcing hspec

Announcing hspec - BDD for Haskell

I've long been interested in Behavior Driven Design and it's something that is strangely missing from the Haskell community. QuickCheck is an amazing tool that I use whenever I can, but BDD has it's uses too, even in Haskell.

hspec aims to be simple and there's only three functions that most people will need to use; describe, it, and hspec. Requirements are always about something and describe is how you say what they are about. describe takes the name of something and a list of requirements for it. The requirements themselves have a plain english description of desired behavior and some Haskell code that verifies the behavior is implemented correctly. The function it takes the english description and the verifying code. So describe and it are the two functions that package up something's requirements and verifiers into a list of Specs.


specs :: IO [Spec]
specs = describe "quantify" [
  it "makes single quantities singular"
    (quantify 1 "thing" == "1 thing"),

  it "makes larger quantities plural"
    (quantify 2 "thing" == "2 things"),

  it "makes zero quantities plural"
    (quantify 0 "thing" == "0 things"),

  it "treats negative quantities just like positive quantities"
    (quantify (-1) "thing" = "-1 thing"),

  it "handles words that end with an 'x' (eg box -> boxes)"
    (pending "no need for this yet")
  ]

hspec aims to be extendable so it is part of a type class, making it easy to add your own verifiers such as hUnit. The currently supported verifiers are an expression that reduces to a Bool, or you can use "pending", or you can use a QuickCheck property. The last requirement's verifier is "pending", representing the fact that this requirement isn't expected to be implemented yet so it doesn't have verifier code. That's all you need right there. Since the Specs are just a Haskell data structure you can evaluate them yourself to see what is successful and what is failing, no need for a test runner.

hspec aims to be useful and if you'd like an easy to read report then there's two extra functions pureHspec and hHspec. pureHspec takes a list of Specs and returns a nicely formatted list of strings documenting each spec and it's status. hHspec takes a handle and IO [Specs] and writes to the handle (usually stdout but it could be a file handle)


>> hHspec stdout specs

quantify
 - makes single quantities singular
 - makes larger quantities plural
 - makes zero quantities plural
 x treats negative quantities just like positive quantities
 - handles words that end with an 'x' (eg box -> boxes)
    # no need for this yet

Finished in 0.00021 seconds

5 examples, 1 failure

We see from the '-' that most requirements for quantify are met, the one with an 'x' is failing, and the one with a '#' and extra details is pending since there's no need for it yet. We also get a summary of how long it took and how many specs failed.

I've got some more ideas for it but I think it's simple enough, extendable enough, and useful enough to release to the Haskell community now.

hspec can be found on github at https://github.com/trystan/hspec

Wednesday, February 9, 2011

Understanding vs NUnit

Can you tell what MysteriousMethod does from looking at these C# unit tests?
  [Test]
  public void Test1()
  {
    var obj = new MysteriousObject();
    Assert.IsTrue(obj.MysteriousMethod(8));
  }

  [Test]
  public void Test2()
  {
    var obj = new MysteriousObject();
    Assert.IsFalse(obj.MysteriousMethod(11));
  }

Maybe it returns true if the input is even, or a single digit, or if it's not prime, or if it's divisible by 4 or 8, or maybe it only returns true for the number 8, I don't know. All I do know is that it returns true for 8 and false for 11.

Can you tell what mysteriousFunction does from looking at these Haskell QuickCheck properties?

  prop_test1 :: Int -> Bool
  prop_test1 x = x `mod` 4 == 0 ==> mysteriousFunction x

  prop_test2 :: Int -> Bool
  prop_test2 x = x `mod` 4 /= 0 ==> not $ mysteriousFunction x

It looks like it returns true if the input is divisible by four and false if it isn't. Pretty clear to me.



I'm working on a Haskell project and it's reminding me why I like QuickCheck so much. Not only does it do a much better job at catching unexpected cases but the meaning and intention of each function is so clear, much clearer than when using xUnit style testing. Going back to C# and NUnit feels weird; you're basically just comparing hard coded values. I find it hard to tell why one value is used instead of something else, i.e. what's essential and what's accidental, especially when the method being tested has several inputs or other variables it relies on. This can lead to bad assumptions and misunderstanding what something actually does. With QuickCheck there's less room for such confusion because the focus is on properties of the values and not the specific values themselves. The clarity of BDD tools (rspec, etc) seems to help, but I wonder what more can be done.

Wednesday, February 2, 2011

Interfaces as object contexts

Here's a possibly useful idea I came up with a few weeks ago. I've come across situations where an object needs different behavior depending on the context or how it's used. Usually the state or strategy design pattern (or a mess of if statements) can handle this, but so can explicit interfaces in C#.

First make an interface for each set of behavior you want.

interface IContextA
{
  string Property { get; }
  int Method(int data);
}

interface IContextB
{
  string Property { get; }
  int Method(int data);
}

Then create the different contexts or scenarios using the interface with the behavior you want.

static void DoStuffInContextA(IContextA example)
{
  Console.WriteLine(example.Property);
  Console.WriteLine(example.Method(8));
}

static void DoStuffInContextB(IContextB example)
{
  Console.WriteLine(example.Property);
  Console.WriteLine(example.Method(8));
}

Then create a class that implements the different behavior.

class MultiContextObject : IContextA, IContextB
{
  string IContextA.Property
  {
    get { return "called in context a"; }
  }

  int IContextA.Method(int data)
  {
    return data + 1;
  }

  string IContextB.Property
  {
    get { return "called in context b"; }
  }

  int IContextB.Method(int data)
  {
    return data - 1;
  }
}

And now you can use interfaces to select which set of behavior you want your object to use.

static void ExplicitInterfaceAsContextTest()
{
  MultiContextObject example = new MultiContextObject();
  DoStuffInContextA(example);
  DoStuffInContextB(example);
}

I think this is neat. It won't replace state and strategy patterns, but there's probably cases where those aren't possible or where this would work better.