I’ve just started playing around with F#, and I wanted to test some of my code. Here’s an introduction to the absolute basics of getting up and running.
Setting up a test project
So to get started I’ve set up a
HelloWorld.sln which contains two projects. The first is my F# library,
HelloWorld.Core, that contains the logic I want to test. The second is another F# library,
HelloWorld.Tests, which amazingly enough will hold my tests. In the test project I’ve referenced the
HelloWorld.Core project we’re testing, and installed the FsUnit package from NuGet, which installs both NUnit and FsUnit (which provides a more F#ish style of assertions).
Some code to test
Let’s open up the default
Library1.fs file in the
HelloWorld.Core project. We’ll add a
Hello module with a
SayHello function that takes a name and returns a
Setting up a test file
We’ll flick over to our
HelloWorld.Test project now, and open up its
Library1.fs file. Let’s replace the default namespace declaration with a module declaration, and import the
FsUnit namespaces using the
We’re now ready to start writing some tests.
There seems a couple of things we need to do to make sure our test is picked up by NUnit (both via the NUnit and ReSharper runners). First, we need a function of type
unit -> unit (we’ll get to this in a minute), and second, we need to decorate that function with a
[<Test>] attribute (the equivalent of
[Test] in C#):
shouldSayHello is the name of our test, and we’re asserting that our
SayHello function returns
"Hello World!" when passed the name
Note that we need to put the
() after the test name. This forces the type of our
shouldSayHello function to be
unit -> unit, which is necessary for NUnit to pick up the test. Omit that and our test won’t appear in our test runner at all, without any hint of an error.
unit type is pretty similar to
void in C#, except we can actually create an instance of
unit by typing an empty pair of parentheses:
unit -> unit means a function which takes
() and returns
There are a few different ways of writing this, such as the alternative below. Use whatever style you prefer.
Running our test
I run the tests by telling ReSharper to run all the tests in the solution. The NUnit runner also works. I haven’t figured out how to run just one test via ReSharper.
If we compile and run either (or both) of these tests, we see them fail as they are expecting
"Hello World!", but we’ve hard coded our function to return
"Hello". We can fix this by updating our
SayHello function in
FsUnit package we installed at the beginning gives us a more F#ish way of expression assertions, compared with NUnit’s standard
Here we call
SayHello "World", and pipe the output to the
should equal "Hello World!" function using the
|> operator. This works just the same as our previous test, but looks more F#ish and reads a bit more nicely.
FsUnit has a few different assertions, as listed in the readme on GitHub.
Quoted identifiers for extra niceness
The last thing we can do to make our test nicer to read is to use quoted identifiers which let us use a sentence for the name of our test function.
The double backticks let us use spaces in the name of our function for extra readability. They show up nicely in test runners too!
To testfinity, and beyond!
And so ends my first, tentative steps into testing F# code using F#. This has been enough to get me started, but the next stop is FsCheck for QuickCheck-style property testing.