Unit testing in F# is a breath of fresh air

I want to start this post off by saying that I was simply blown away with unit testing in F#. Before I go on I want to give reference to the excellent F# for fun and profit blog for getting me started.

Unit testing and F# are a match made in heaven. I think the best thing to do before I go on is to show you a unit test in C#:


public class AllIndexOfTests
{
    [Test]
    public void AllIndexOfhellInHelloHelloIsCorrect()
    {
        var allIndexOf = new AllIndexOf();
        var result = allIndexOf("hello hello", "hello");
        result.SequenceEqual(0, 6).Should().BeTrue();
    }

}

Now in F#:

[<Test>]
    let ``the string 'hello hello' contains the string 'hell' at indexes 0 and 6``() =
        allIndexOf "hello hello" "hell" |> should equal [0; 6]

Check out how the F# code is self describing. Due to the fact that in F# you can put whitespace in a function by escaping the name with the double back tick, the function name can be self describing with spaces which makes it readable. To get the C# code to look as clean as above requires the use of quite a lot of libraries and careful design of your code. Even then you can’t get that close. The F# just reads like English. I would go as far as to say someone who did not understand code could read that test and understand what the function should do.

The testing framework I am using to obtain this syntax is FsUnit. Which is built on top of NUnit. Here are the complete set of tests for the GridSearch solution to the HackerRank problem I went through last time:

module allIndexOf =
    [<Test>]
    let ``the string 'hello hello' contains the string 'hell' at indexes 0 and 6``() =
        allIndexOf "hello hello" "hell" |> should equal [0; 6]

    [<Test>]
    let ``the string 'hello world' does not contain the string 'kevin' ``() =
        allIndexOf "hello world" "kevin" |> should equal []

module find =
    [<Test>]
    let ``the string '123' is in the grid '444 123 444' at [(0,1)]``() =
        find ["444"; "123"; "444"] "123" 0 |> should equal [(0,1)]

    [<Test>]
    let ``the string '123' is in the grid '444123 981231 123122' at [(0,1)]``() =
        find ["444123"; "981231"; "123122"] "123" 0 |> should equal [(3,0); (2,1); (0, 2)]

    [<Test>]
    let ``the string '123' is not in the grid '123 777 444' when the first row is skipped ``() =
        find ["123"; "777"; "444"] "123" 1 |> should equal []

module findExact =
    [<Test>]
    let ``the string '123' is in the grid '444 123 444' is exactly at 0, 1``() =
        findExact ["444"; "123"; "444"] "123" 0 1 |> should equal true

    [<Test>]
    let ``the string '77' is in the grid '9999 9977 0987 0987' is exactly at 2, 1``() =
        findExact ["9999"; "9977"; "0987"; "0987"] "77" 2 1 |> should equal true

    [<Test>]
    let ``the string '865' is not in the grid '9999 9977 0987 0987' is exactly at 2, 1``() =
        findExact ["9999"; "9977"; "0987"; "0987"] "865" 2 1 |> should equal false

    [<Test>]
    let ``the string '77' is not in the grid '9999 9977 0987 0987' is exactly at 3, 3``() =
        findExact ["9999"; "9977"; "0987"; "0987"] "77" 3 3 |> should equal false

module gridContains =
    [<Test>]
    let ``the grid '444 123 444 555' contains the grid '123 444 555 ``() =
        gridContains  ["444"; "123"; "444"; "555"] ["444"; "123"; "444"] |> should equal true

    [<Test>]
    let ``the grid '44488 12311 44490 55598 778899' contains the grid '44 55 ``() =
        gridContains  ["44488"; "12311"; "44490"; "55598"; "778899";] ["44"; "55"] |> should equal true

    [<Test>]
    let ``the grid '44488 12311 44490 55598 778899' does not contain the grid '88 88 ``() =
        gridContains  ["44488"; "12311"; "44490"; "55598"; "778899";] ["88"; "88"] |> should equal false

The fact this fits in such a small space, is succinct and to the point makes it such a good fit for unit testing. I would even argue that even if you use C# for your main application writing your tests in F# could save you time and make your tests much more readable.

If you look at the code listing you will see that I have created the tests all inside the module GridSearchTests. I have then grouped each set of tests under a module that is named the same as the function they are testing. This means in the resharper test runner you get the following:

tests

Which I think is really sweet. Each function is listed along with the test cases that can be read in normal English. Rather than in C# you often name your test cases using camel casing. Meaning that when the test cases become long it can be hard to read them.

To check out the code from this post clone my HackerRankInFSharp repository on github. Please feed back your F# unit testing experiences in the comments.

Advertisements

Mocking Frameworks in .Net

As a contractor I have seen a lot of different companies’ code bases and been on many different projects. Most companies now employ TDD (which is a good thing). This means that often you need a mocking framework. Mocking frameworks are ten to the dozen and I have used many different ones over the years.

The most common mocking framework in .Net that I have come across by far is Moq. I quite like Moq but the syntax is a bit clunky. For example to setup a mock repository to return a fake customer:

 var mockRepository = new Mock();
 mockRepository.Setup(m =&gt; m.GetCustomer(It.IsAny()).Returns(new Customer{ Id = 1234, Name = "Fred" });
 var customerController = new CustomerController(mockRepository.Object);
 

What I don’t like is that the variable mockRepository is not an ICustomerRepository it is a Mock<ICustomerRepository>. The Mock is a wrapper around your type. This means that when you inject your mock into the class you are testing you need to use the .Object property as can be seen on line 3 above.

Compare this to FakeItEasy:

 var mockRepository = A.Fake();
 A.CallTo(m =&gt; m.GetCustomer(A.Ignored).Returns(new Customer{ Id = 1234, Name = "Fred" });
 var customerController = new CustomerController(mockRepository);
 

This feels so much cleaner to me because this time mockRepository variable is a ICustomerRepository. The A.Fake<T>() method is a factory method from the FakeItEasy library that does some clever work with a dynamic proxy to fill the provided interface (in this case ICustomerRepository) on the fly. This also means that when we pass the mock into our CustomerController this time we just pass mockRepository, we don’t need to use the .Object extension which feels much cleaner (see line 3 in the 2nd snippet above).

Which mocking frameworks have you used? What are the pros/cons?