Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

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.

This entry was posted in F#, TDD/BDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.fuar-standlari.com fuar standları izmir

    thanksss..

  • http://www.hasgulrentacarizmir.com izmir oto kiralama

    thanks.

  • http://www.hitsihirbazi.com hit

    thankss

  • http://podwysocki.codebetter.com Matthew.Podwysocki

    @Bruce

    So noted and fixed

    Matt

  • http://galactic-patrol.spaces.live.com Bruce

    The link to Gallio is bad – you need to add ‘www':

    http://www.gallio.com

  • http://podwysocki.codebetter.com Matthew.Podwysocki

    @Jim Burger

    Interesting way of tackling the problem. The forward operator is especially interesting in this case. I think the syntax can be made a bit more concise though, but I think it’s pretty clean. Definitely throw it out there for public consumption

    Matt

  • http://podwysocki.codebetter.com Matthew Podwysocki

    @Jeff Brown

    I did copy over those xUnit.net dlls and it still didn’t register, so I’m not sure what else I’d have to do to get it to work.

    Matt

  • http://blog.bits-in-motion.com/ Jeff Brown

    Sorry, I guess I need to upgrade the xUnit.net plugin to the latest version.

    You might try just dropping the new xunit.dll into the Gallio bin folder after installation.

  • http://nervoustych.com/blog Jim Burger

    Thats good news Matt,

    I’ve also been looking at some sort of BDD framework for F#. I like Specter (in Boo) so Im thinking about something like this: (please forgive syntax errors)

    let sut = createSUT()

    let at_the_bar() =
    Context “at the bar”
    |> Specify (“if I drink too much I fail”, sut,
    fun s -> s.DrinkTenBeers())
    |> Must.Throw (type FailureException)

    Any thoughts to this approach?

  • http://nervoustych.com/blog Jim Burger

    Hi Matt,

    I’ve too have been trying out various BDD semantics in the hope of writing a BDD framework. Lately I’ve been looking at how I might get something close to Specter (in Boo) Something along the lines of…(forgive any syntax errors)

    let at_the_bar() =
    Context “at the bar”
    |> Specify (“when I drink too much I fail”, sut,
    fun s -> s.DrinkTenBeers())
    |> Must.Throw (type FailureException)

    Hopefully in the next few weeks I’ll have something on codeplex for people to try out/modify.