Removing usage of Arb.registerByType from Xunit test using FsCheck

84 views Asked by At

I am testing a round-trip of a Thoth.Json Encoder / Decoder pair.

It looks like this:

type CustomArbitrary =
  static member String() =
    Arb.Default.String()
    |> Arb.filter (not << isNull)

[<Fact>]
let ``Encode.foo Decode.foo round-trip`` () =
  let roundTrip (x : Foo) =
    let json =
      x
      |> Encode.foo
      |> Encode.toString 2

    let decoded =
      json
      |> Decode.fromString Decode.foo

    Ok x = decoded

  // Necessary?
  Arb.registerByType (typeof<CustomArbitrary>) |> ignore

  Check.QuickThrowOnFailure (roundTrip)

The test fails if I do not filter out null values for System.String. However, null is not a proper value inside Foo so that is fine.

However, I don't like the usage of Arb.registerByType here due to global state etc.

How can I rewrite this test so that Arb.registerByType is not necessary?

Ideally, I would design a FsCheck config once and pass that to each test.

1

There are 1 answers

0
Brian Berns On BEST ANSWER

Using vanilla FsCheck

Create the config once like this:

let config =
    {
        FsCheck.Config.Default with
            Arbitrary = [ typeof<CustomArbitrary> ]
    }

Then use it to check each test like this:

Check.One(config, roundTrip)

Using FsCheck.Xunit

If you switch to Properties/Property instead of Fact, you don't even need an explicit config instance or the Check class:

open FsCheck.Xunit

[<Properties(Arbitrary=[| typeof<CustomArbitrary> |])>]
module MyTests =

    [<Property>]
    let ``Encode.foo Decode.foo round-trip`` (x : Foo) =
        let json =
          x
          |> Encode.foo
          |> Encode.toString 2

        let decoded =
          json
          |> Decode.fromString Decode.foo

        Ok x = decoded

    [<Property>]
    let ``Some other test`` () =
        true

More info on this approach here.

By the way, be careful about using . characters in your test names, because some test frameworks (e.g. Visual Studio) use them to define a test hierarchy.

Related Questions in F#