The Unit Testing Story in F# Revisited

Last week I posted about some troubles I was having with the unit testing frameworks for F#.  Today, Brad Wilson announced the release of xUnit.net 1.0.1 which addressed the change in the F# compiler as well as integration with ASP.NET MVC Preview 3 which was just released.  As always you can find the latest bits on CodePlex.  There was a change in the way F# was compiling the modules as static classes which was not expected in previous versions. 

Running the Tests Again

Now, I'm able to run my functions just as before and the runner will now recognize them.  Below is just a simple example of some unit tests to determine whether numbers are prime or not.  I'm extending the System.Int32 to add a property to the instance to determine whether it is prime.  Just to prove a point on how flexible F# really is, I'm also able to extend the Int32 class using static methods, something that you cannot do with C# and extension methods.  More and more, I love the language itself and finding myself trapped sometimes by the limits of C#.  But, that's sidetracking, so let's get to the unit tests.

#light

#R @"D:\Tools\xunit-1.0.1\xunit.dll"

open Xunit

let isPrimeNumber(i) =
  let limit = int(sqrt(float(i)))
  let rec check j =
    j > limit or (i % j <> 0 && check(j + 1))
  check 2
   
type System.Int32 with
  member i.IsPrime
    with get () = isPrimeNumber(i)
   
  static member IsPrimeNumber(x) =
    isPrimeNumber(x)

[<Fact>]
let IsPrime_WithPrimeNumber_ShouldReturnTrue() =
  Assert.True((7).IsPrime)
   
[<Fact>]
let IsPrime_WithNonPrimeNumber_ShouldReturnFalse() =
  Assert.False((21).IsPrime)
  Assert.False(System.Int32.IsPrimeNumber(45))

And then when I run it through the GUI runner, I sure enough get two passing tests.  It was asked of me last week at the Philly ALT.NET meeting about TDD with F# and I see no problem with this at all, and in fact I actively encourage it.  But, you have to think about this in a different light when talking about objects and behaviors, and then turning around to functions and behaviors.

Getting Going with Gallio

As I mentioned last time, Jeff Brown has been hard at work to support the F# community as well.  I was able to get the right build going of Gallio finally after there may have been some mixups with getting the latest code.  Anyhow, I am now able to get these same tests to work, but using MbUnit version 3 and through the Gallio Icarus Runner.  If you're not familiar with Gallio, it is an open platform of tools and runners that is extensible to all testing frameworks.  Jeff Brown talked about it on Hanselminutes with Brad Wilson of xUnit.net fame, Roy Osherove and Charlie Poole of NUnit on the Past, Present and Future of Unit Testing Frameworks.

So, let's just modify the above code to migrate to Gallio with MbUnit version 3 and see how we do:

#light

#R @"D:\Program Files\Gallio\bin\Gallio.dll"
#R @"D:\Program Files\Gallio\bin\MbUnit.dll"

open MbUnit.Framework

let isPrimeNumber(i) =
  let limit = int(sqrt(float(i)))
  let rec check j =
    j > limit or (i % j <> 0 && check(j + 1))
  check 2
   
type System.Int32 with
  member i.IsPrime
    with get () = isPrimeNumber(i)
   
  static member IsPrimeNumber(x) =
    isPrimeNumber(x)

[<Test>]
let IsPrime_WithPrimeNumber_ShouldReturnTrue() =
  Assert.IsTrue((7).IsPrime)
   
[<Test>]
let IsPrime_WithNonPrimeNumber_ShouldReturn_False() =
  Assert.IsFalse((21).IsPrime)
  Assert.IsFalse(System.Int32.IsPrimeNumber(45))
 
And we can notice through the Gallio runner that it's only detecting the MbUnit tests right now, unfortunately.  Hopefully that issue will be resolved soon.



BDD Specs in F#?

F# is a pretty flexible language for unit testing and even BDD style.  I wonder if we could take some lessons from the spec BDD framework for Scala and apply to F#.  Just a thought...

If you're not familiar with specs, it's a BDD framework with some interesting syntax that I'm still coming to terms with.  But the concept looks interesting.  Take a look at a quick example and see if it speaks to you.

package podwysocki.specs

object scalaSpecExample extends Specification {
  "A hello world spec" should {
    "return something" in {
       "hello" mustBe "hello"
    }
  }
}

As I've played around with Scala, this is a pretty interesting concept.  I'm much more a fan of F# as a language, but still there are some interesting pieces to Scala.  I'm also interested in using MSpec from Aaron Jensen at some point, but have a bit on my plate and other points of focus right now. 

Wrapping It Up


In the mean time, we have another testing framework to consider.  Me, personally, I prefer xUnit.net because of the functional aspects of Assert.Throws and so on.  But, that option is up to you quite frankly.  There is a good story to be told here with regards to unit testing and F# that is not to be overlooked. 

kick it on DotNetKicks.com

24 Comments

Comments have been disabled for this content.