Most common .Net testing tools work in F#, but that’s not the end of the story. F# adds many more tools and techniques besides, lets take a look at a few of them:
1) Back tick methods
F# lets you write method names with whitespace by escaping the name in back-ticks:
let [<Fact>] ``2 + 2 should equal 4`` () =
Assert.Equal(4, 2+2)
This is also handy when writing step definitions for acceptance tests:
let [<Then>] ``I should have (.*) black jumpers in stock`` (n:int) =
let passed = (stockItem.Count = n)
Assert.True(passed)
TickSpec provides a lightweight library for automating acceptance tests in F# along with SpecFlow which now supports back-tick methods (although for SpecFlow you’ll need a C# project too).
2) Mocking
In F# you can easily create mock objects without frameworks using object expressions:
let [<Test>] ``at 15:00 the sun image should be expected`` () =
let time = { new ITime with member __.GetHour () = 15 }
// ...
Along with all the standard .Net mocking frameworks like Moq, F# also has Foq:
let [<Test>] ``at 01:00 the moon image should be expected`` () =
let time = Mock<ITime>.With(fun mock -> <@ mock.GetHour() --> 01 @>)
// ...
And now there’s AutoFixture support in the form of AutoFixture.AutoFoq.
3) Fluent Assertions
FsUnit lets you write your assertions very close to how you might write your test names:
let [<Test>] ``2 + 2 should equal 4`` () =
2 + 2 |> should equal 4
While unquote lets you write tests like code:
let [<Test>] ``2 + 2 = 4`` () =
test <@ 2 + 2 = 4 @>
4) FsCheck
FsCheck is a random testing framework based on Haskell’s QuickCheck that lets you assert properties on functions:
let revRevIsOrig (xs:list<int>) = List.rev(List.rev xs) = xs
Check.Quick revRevIsOrig
In the check above FsCheck will randomly create lists of integers to test that the property holds (reversing a list twice should take you back to the original list). If it fails it pares back the input to the shortest list that would make the property fail.
5) Code Coverage
Not F# specific per se, but full fat Visual Studio 2012 comes with a test runner and code coverage tools built-in, it even highlights code that isn’t covered by tests for you:
Happy testing!