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.

No comments:

Post a Comment