-- Shakespeare, Romeo and Juliet
Act I, Scene IV, Line 31
I've started using Unquote for my assertions with F# xUnit tests. I find that its step-by-step failure messages really help in figuring out what is going on.
One thing that really throw me when I first used it was the System.MissingMethodException exception that Unquote was throwing at runtime. Luckily I was able to find this StackOverflow answer. It seems that you need to do a binding redirect for FSharp.Core, so you'll need to set up an App.config file in your test project like this example of the Coin Changer kata (using MapFold).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8" ?> | |
<configuration> | |
<runtime> | |
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | |
<dependentAssembly> | |
<assemblyIdentity name="FSharp.Core" | |
publicKeyToken="b03f5f7f11d50a3a" | |
culture="neutral"/> | |
<bindingRedirect oldVersion="4.3.1.0" | |
newVersion="4.4.0.0"/> | |
</dependentAssembly> | |
</assemblyBinding> | |
</runtime> | |
</configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace CoinChanger | |
module Changer = | |
let change coins amount = | |
coins | |
|> List.mapFold | |
(fun amount coin -> List.replicate <| amount / coin <| coin, amount % coin) | |
amount | |
|> fst | |
|> List.reduce (@) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace CoinChangerTests | |
module ChangerTests = | |
open Xunit | |
open Swensen.Unquote | |
open CoinChanger.Changer | |
[<Theory>] | |
[<InlineData(0)>] | |
[<InlineData(1)>] | |
[<InlineData(99)>] | |
let ``given pennies it must return coins equal to amount given`` amount = | |
let pennies = [1] | |
test <@ | |
change pennies amount |> List.length = amount | |
@> | |
[<Theory>] | |
[<InlineData(0, 10)>] | |
[<InlineData(1, 5)>] | |
[<InlineData(42, 25)>] | |
[<InlineData(99, 20)>] | |
let ``given number of coins and value it must return number of coins`` number value = | |
let coins = [value] | |
test <@ | |
change coins <| number * value |> List.length = number | |
@> | |
[<Theory>] | |
[<InlineData(1)>] | |
[<InlineData(10)>] | |
[<InlineData(99)>] | |
let ``given coin values it must return coins of that value`` value = | |
let coins = [value] | |
let amount = 99 | |
test <@ | |
let unique = change coins amount |> List.distinct | |
unique |> List.length = 1 | |
&& | |
unique |> List.head = value | |
@> | |
[<Fact>] | |
let ``given full register and 1 of each coin it must return 1 of each coin`` () = | |
let register = [25; 10; 5; 1] | |
let amount = List.sum register | |
test <@ | |
change register amount |> List.distinct = register | |
@> | |
[<Theory>] | |
[<InlineData(0)>] | |
[<InlineData(1)>] | |
[<InlineData(42)>] | |
[<InlineData(99)>] | |
let ``given full register it must return coins summing to amount`` amount = | |
let register = [25; 10; 5; 1] | |
test <@ | |
change register amount |> List.sum = amount | |
@> |
Happy coding.