4 reasons to write your tests in F#

I have recently started to introduce F# into actual production code bases I am working on. This is a bit of a milestone for me, since my dealings with F# up until recently have been limited to hobby projects.

This also means I have started writing tests in F#, and not just for the F# bits, I've actually switched to writing all tests in F#. Here a couple of resons why I suggest you should do the same.

Learning F# in the real world environment

The most common responses I hear from people reluctant to try out F# are often a variation of:

"I don't see how I will be able to use F# in my day job".

This may be a valid concern. Introducing a new programming language to the mix in an established project, with an established team, might not be that easy. But it seems likely introducing a new language in a small test project might be a little easier.

F# is a good fit for writing tests, and starting with tests gives you a chance to become more familiar with the language in an actual development setting.

Descriptive test case naming

With F# you have the option of using "ticked function names". Basically this is a way of doing quoted function names, allowing you use spaces and full sentences as function names. While this might seem dirty, it's very convenient for test naming.

Take a look at the following code that I lifted from the FsUnit homepage.

[<Fact>]
let ``with simple scores should get the expected score.`` () =
  scoreBowls [1;2;3] |> should equal 6

This syntax, while not the most pleasing to the eye, really makes for readable test overviews. Here is a screenshot of the tests in the NCrunch overview (if you haven't tried NCrunch you should go check it out).

Pretty and readable NCrunch overview

That beats CamelCasing and underscores any day of the week.

Terse tests

A neat property of the FSharp language is that it is less verbose than a lot of the "bracket languages". The reason for this (in my opinion) is not just about the syntax, but also the coding style the language pushes you towards.

Considering syntax alone, here is a simple example of a "test suite" for a "Multiplier"-object (written in C#). The test suite is implemented twice, in C# and F# respectively.

C#

using MyOperators;
using Xunit;

namespace MyOperation.Tests.CSharp
{
    public class Tests
    {
        [Fact]
        public void GivenAMultiplierWithAFactorOf5_WhenMultiplying2_ShouldGive10()
        {
            Assert.Equal(10, new Multiplier(5).Multiply(2));
        }

        [Fact]
        public void GivenAMultiplierWithAFactorOf10_WhenMultiplying5_ShouldGive50()
        {
            Assert.Equal(50, new Multiplier(10).Multiply(5));
        }

        [Fact]
        public void GivenAMultiplierWithAFactorOf20_WhenMultiplying10_ShouldGive200()
        {
            Assert.Equal(200, new Multiplier(20).Multiply(10));
        }
    }
}

F#

namespace MyOperators.Tests.FSharp
open Xunit
open FsUnit.Xunit
open MyOperators

module ``Multiplier Tests`` =

    [<Fact>] 
    let ``given a multiplier with a factor of 5, when multiplying with 2, should be 10`` () =
        Multiplier(5).Multiply(2) |> should equal 10

    [<Fact>] 
    let ``given a multiplier with a factor of 10, when multiplying with 5, should be 50`` () =
        Multiplier(10).Multiply(5) |> should equal 50

    [<Fact>] 
    let ``given a multiplier with a factor of 20, when multiplying with 10, should be 200`` () =
        Multiplier(20).Multiply(10) |> should equal 200

While the ceremony is the same for both languages (namespace, references etc), each of the tests sheds a couple of lines worth of brackets and whitespace by transitioning from C# to F#. Combined with the ticked test names, I find the F# version to be a lot more natural to read.

Just as good tooling

The tools you use shouldn't care if you write your tests in FSharp or some other .NET language. The outcome should be the same. It took me ten minutes to get my F#-based XUnit tests running with FsUnit and the wonderful NCrunch Visual Studio plugin.

Ready to try it out?

If you've been wanting to try out F# but haven't found a good way to fit it into the project you are working on, tests are a really good place to start. It has a few advantages over other languages, and it will allow you to experiment with F# in a safe environment. Enjoy! :)

View Comments