I agree that this can be confusing. It's simplest to define a custom type and then create a generator for it:
open FsCheck
open FsCheck.Xunit
type Zero = MkZero of int
let isZero (MkZero x) = (x = 0)
type Arbs =
// This is the generator for the Zero type.
static member Zero() =
MkZero 0
|> Gen.constant
|> Arb.fromGen
[<Property>]
let TestSample zeros =
List.forall isZero zeros
[<assembly: Properties(
Arbitrary = [| typeof<Arbs> |])>]
do ()
The Zero
type has a generator that creates zero values. The TestSample
property then confirms that every element of an arbitrary list of zeros is indeed zero. FsCheck will automatically generate lists of various sizes to confirm this. You can run with Verbose = true
to see them if you want.
Since you want to use Xunit properties, you have to register the generator, as described here.
As the documentation mentions, you shouldn't use Gen.sample
when writing properties.