Home > F# > FsUnit – Test Fsharp with Fsharp

FsUnit – Test Fsharp with Fsharp

FsUnit - Test Fsharp with Fsharp

February 11th | 2009

FsUnit – Test F# with F#

I recently spent some time putting together an F# lab with a series of unit tests designed to help teach the language. I started out with a set of Nunit tests in C#, but kept running head-first into type problems with the method signatures and return types. Another hiccup was that my VS 2008 C# code couldn’t see my F# code until I referenced the generated F# dll directly via Browsing. Adding a simple project reference didn’t work.

For example, here’s a simple F# function that returns the square of the input for any member with (*) defined and a C# assert based on it.

F# module:


namespace Samples

module SampleOne =

let inline Square (x : ^x) = x * x;

C# code:

Assert.AreEqual(9, Samples.SampleOne.Square(3));

Seems simple enough, right? Except for the build error. “The Type arguments for method ‘Samples.SampleOne.Square<x,a>(x)’ cannot be inferred from the usage. Try specifying the type arguments explicitly.” What the compiler is telling us here is that we’re calling a generic function without specifying the types.

To make the compiler happy, we have to do the following instead:

Assert.AreEqual(9, Samples.SampleOne.Square<int, int>(3));

Elegant? No, not really. The syntactic magic that F# uses to allow us to infer types is not available within C#.

Here’s a simple F# function that calls ToString on all members of a list and returns it as a new list.

let ListToString x = List.map (fun x → x.ToString()) x;

Its signature in F# looks like: val WorkOnList : (`a → string list)

In C# … Microsoft.FSharp.Core.FSharpFunc<Microsoft.FSharp.Collections.FSharpList<b>, Microsoft.FSharp.Collections.FSharpList<string>> SampleOne.WorkOnList<a,b>(a x)

Confusing, at best. Luckily there’s a testing framework that avoids these issues and is designed for F#.

FsUnit to the Rescue

FsUnit is a library that defines a simple, easy-to-use testing syntax within F#. It currently works with NUnit, but is intended to work with MbUnit, xUnit, and MsTest in the future. It’s a breeze to set up, simply reference nunit.framework, FsUnit.NUnit, and include the FsUnit F# script that sets up the syntax.

Using FsUnit, we can describe our functions and write a test for them as follows:

namespace Tests
open NUnit.Framework
open FsUnit

module module1 =
    let inline public Square x = x * x;

    type ``Sample Tests`` ()=

        let WorkOnList x = List.map (fun (x) -> x.ToString()) x;
        let lame x = List.head x;

        [<Test>] member test.
         ``Test One`` ()=
            Square 5 |> should equal 25;
            Square 0 |> should equal 0;
            Square 1.5 |> should equal 2.25;
            WorkOnList [1;2;3;4;5] |> should equal ["1";"2";"3";"4";"5"]

Much more elegant and concise than the C# mess above. Spaces in test names are allowed—a feature I love. I’ve written far too many tests along the lines of ShouldCorrectlyDoOperationWhenValueAandValueBDoNotExceedValueC.

Languages typically use spaces to separate words instead of capitalization for a reason.

Keep in mind that this test syntax does not cause a compile time error if types do not match. For example, a function defined as let x = 0; does not cause a compile error when tested with x |> should equal “horse”.

In conclusion, I recommend giving FsUnit a try if you intend to test F# code. Test in the language you wrote the code in!

David Cooksey is a Senior .NET Developer at Thycotic Software, an agile software services and product development company based in Washington DC. Secret Server is our flagship password management software product.

Categories: F#
  1. Kevin Jones
    February 11, 2010 at 7:27 pm

    I almost want to start writing all of my tests in F# for a different reason.

    The white space is non issue, just use underscores. It’s close enough to a space that your eyes will read it as one. I’m not sure why some people perceive underscores as evil in test names.

    My favorite feature is the elegant assertions. It almost reads like English.

    Square 5 |> should equal 25

    Is better than

    Assert.AreEqual(25, Class.Square(5));

    I’m sure you can come up with some extension methods for the object class that make a fluent-like syntax, but this just can’t be beat.

  1. March 10, 2010 at 8:58 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: