Sunday, February 21, 2016

Unquote, App.config, and You

"What curious eye doth quote deformities?"
-- 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).

<?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>
view raw App.config hosted with ❤ by GitHub
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 (@)
view raw Changer.fs hosted with ❤ by GitHub
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
@>
view raw ChangerTests.fs hosted with ❤ by GitHub


Happy coding.