Home

Awesome

FsUnit

FsUnit is a set of libraries that makes unit-testing with F# more enjoyable. It adds a special syntax to your favorite .NET testing framework. FsUnit currently supports NUnit, MbUnit, xUnit, and MsTest (VS11 only).

The goals of FsUnit are:

Syntax

With FsUnit, you can write unit tests like this:

One object equals or does not equal another:

1 |> should equal 1

1 |> should not' (equal 2)

One numeric object equals or does not equal another, with a specified tolerance:

10.1 |> should (equalWithin 0.1) 10.11

10.1 |> should not' ((equalWithin 0.001) 10.11)

A string does or does not start with or end with a specified substring:

"ships" |> should startWith "sh"

"ships" |> should not' (startWith "ss")

"ships" |> should endWith "ps"

"ships" |> should not' (endWith "ss")

A List, Seq, or Array instance contains or does not contain a value:

[1] |> should contain 1

[] |> should not' (contain 1)

A List or Array instance has a certain length (NUnit only):

anArray |> should haveLength 4

A Collection instance has a certain count (NUnit only):

aCollection |> should haveCount 4
A function should throw a certain type of exception:
(fun () -> failwith "BOOM!" |> ignore) |> should throw typeof<System.Exception>

A number of assertions can be created using the be keyword:

true |> should be True

false |> should not' (be True)

"" |> should be EmptyString

"" |> should be NullOrEmptyString

null |> should be NullOrEmptyString

null |> should be Null

anObj |> should not' (be Null)

anObj |> should be (sameAs anObj)

anObj |> should not' (be sameAs otherObj)

11 |> should be (greaterThan 10)

9 |> should not' (be greaterThan 10)

11 |> should be (greaterThanOrEqualTo 10)

9 |> should not' (be greaterThanOrEqualTo 10)

10 |> should be (lessThan 11)

10 |> should not' (be lessThan 9)

10.0 |> should be (lessThanOrEqualTo 10.1)

10 |> should not' (be lessThanOrEqualTo 9)

0.0 |> should be ofExactType<float>

1 |> should not' (be ofExactType<obj>)

[] |> should be Empty // NUnit only

[1] |> should not' (be Empty) // NUnit only

"test" |> should be instanceOfType<string> // Currently, NUnit only and requires version 1.0.1.0+

"test" |> should not' (be instanceOfType<int>) // Currently, NUnit only and requires version 1.0.1.0+
	
2.0 |> should not' (be NaN) // Currently, NUnit only and requires version 1.0.1.0+

[1;2;3] |> should be unique // Currently, NUnit only and requires version 1.0.1.0+

Deprecated Functions

Prior to version 1.1.0.0, FsUnit implemented a function named not that overwrote the F# operator of the same name. This is not ideal, so as of version 1.1.0.0 the FsUnit function has been renamed to not' (not + single-quote). If you need or want the previous function, it can be made available by opening the FsUnitDepricated module.

Visual Studio 11 Support

Visual Studio 11 support is available for all 4 of the targetted testing frameworks. FsUnit.MsTest is supported only in VS11 and no additional steps are required to use it. FsUnit for NUnit, FsUnit.MbUnit, and FsUnit.xUnit target F# 2.0 as well as F# 3.0. Because of this, a few additional steps are required in order to use these libraries in VS11. After installing one of these packages, add an App.config file to the project (if one doesn't already exist). Build the project and then run the command "Add-BindingRedirect projectname" (where projectname is the name of your test project) in the NuGet Package Manager Console. This command will update the App.config to include binding redirects from previous version of FSharp.Core to FSharp.Core version 4.3.0.0. More information about this command can be found at http://docs.nuget.org/docs/reference/package-manager-console-powershell-reference.

NuGet

NuGet packages are available for each of the supported testing frameworks:

Examples

The following are examples of FsUnit with MbUnit, xUnit, and NUnit respectively:

MbUnit:

module Test.``Project Euler - Problem 1``

open MbUnit.Framework
open FsUnit.MbUnit

let GetSumOfMultiplesOf3And5 max =  
	seq{3..max-1} |> Seq.fold(fun acc number ->  
						(if (number % 3 = 0 || number % 5 = 0) then   
							acc + number else acc)) 0 

[<Test>]
let ``When getting sum of multiples of 3 and 5 to a max number of 10 it should return a sum of 23`` () =  
	GetSumOfMultiplesOf3And5(10) |> should equal 23 

xUnit (Thanks to Keith Nicholas and "Julian" from hubFS for this example! http://cs.hubfs.net/forums/thread/3938.aspx):

module BowlingGame.``A game of bowling``

open Xunit
open FsUnit.Xunit

let (|EndOfGame|IncompleteStrike|Strike|Normal|Other|) (l, frame) =
	match l with
	| _ when frame = 11            -> EndOfGame(0)
	| [10;s]                       -> IncompleteStrike(10+s+s)
	| 10::s::n::tail               -> Strike(10+s+n, s::n::tail)
	|  f::s::n::tail when f+s = 10 -> Normal(f+s+n,  n::tail)
	|  f::s::n::tail               -> Normal(f+s,    n::tail)
	| ls                           -> Other(List.fold (+) 0 ls)

let scoreBowls bowls =
	let rec scoreBowls' frame l current_score =
		let nextframe = scoreBowls' (frame+1)
		match (l, frame) with
		| EndOfGame(score)        -> current_score + score
		| IncompleteStrike(score) -> current_score + score
		| Strike(score, l)        -> nextframe l (current_score + score)
		| Normal(score, l)        -> nextframe l (current_score + score)
		| Other(score)            -> current_score + score
	scoreBowls' 1 bowls 0

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

[<Fact>]
let ``with a spare should get the expected score (spare).`` () =
	scoreBowls [2;8;1] |> should equal 12

[<Fact>]
let ``with a strike should get the expected score (strike).`` () =
	scoreBowls [10;1;2] |> should equal 16

[<Fact>]
let ``that is perfect should get a score of 300.``() =
	scoreBowls [for i in 1..18 -> 10] |> should equal 300

[<Fact>]
let ``with spares in the last frame should get the expected score (spare in last frame).`` () =
	scoreBowls ([for i in 1..18 -> 0] @ [2;8;1]) |> should equal 11

[<Fact>]
let ``with a strike in the last frame should get the expected score (strike in last frame).`` () =
	scoreBowls ([for i in 1..18 -> 0] @ [10;10;1]) |> should equal 21

[<Fact>] 
let ``with double strikes should add the score of the first strike to the score of the second.`` () =
	scoreBowls [10;10;1] |> should equal 33

[<Fact>]
let ``that looks like an average bowler's game should get the expected score (example game).`` () =
	scoreBowls [1;4;4;5;6;4;5;5;10;0;1;7;3;6;4;10;2;8;6] |> should equal 133

NUnit (Note: NUnit can also be utilized without specifying a type as in the examples for MbUnit and xUnit):

namespace LightBulb.Tests

open NUnit.Framework
open FsUnit

type LightBulb(state) =
	member x.On = state
	override x.ToString() =
		match x.On with
		| true  -> "On"
		| false -> "Off"

[<TestFixture>] 
type ``Given a LightBulb that has had its state set to true`` ()=
	let lightBulb = new LightBulb(true)

	[<Test>] member x.
	 ``when I ask whether it is On it answers true.`` ()=
			lightBulb.On |> should be True

	[<Test>] member x.
	 ``when I convert it to a string it becomes "On".`` ()=
			string lightBulb |> should equal "On"

[<TestFixture>]
type ``Given a LightBulb that has had its state set to false`` ()=
	let lightBulb = new LightBulb(false)

	[<Test>] member x.
	 ``when I ask whether it is On it answers false.`` ()=
			lightBulb.On |> should be False

	[<Test>] member x.
	 ``when I convert it to a string it becomes "Off".`` ()=
			string lightBulb |> should equal "Off"

Getting Involved

GitHub makes collaboration very easy. To get involved with FsUnit, simply follow the directions provided by GitHub to fork this repository, then implement lots of cool stuff, and finally send a pull request.

A few things to keep in mind:

Release Notes