How do I register an Arbitrary instance in FsCheck

2020-07-10 07:32发布

问题:

I've got a type Average with a field count that's a positive int64 and a double field called sum.

I made an arbitrary that generates valid instances with

 let AverageGen = Gen.map2 (fun s c -> Average(float(s),int64(int(c))) (Arb.Default.NormalFloat().Generator)  (Arb.Default.PositiveInt().Generator) |> Arb.fromGen

How do I get this to be generate arguments with type Average in Property style tests in xUnit?

[<Property>]
static member average_test(av:Average) = ...

回答1:

type Generators =
    static member TestCase() =
        { new Arbitrary<TestCase>() with
            override x.Generator =
                gen { ...
                      return TestCase(...) }}

[<Property(Arbitrary=[|typeof<Generators>|])>]


回答2:

I think Vasily Kirichenko's solution is the correct one, but just for completeness sake, I've also been able to make it work with this imperative function invocation style:

do Arb.register<Generators>() |> ignore

...if you assume a Generators class as in Vasily Kirichenko's answer.


Edit, much later...

While the above, imperative approach may work, I never use it because of its impure nature. Instead, I sometimes use the Arbitrary directly from within the test. With the AverageGen value above (which I'll rename to averageGen, because values should be camelCased), it could look like this:

[<Property>]
let member average_test () =
    Prop.forAll averageGen (fun avg ->
        // The rest of the test goes here... )


标签: f# xUnit fscheck