Hello all.
I’m still having issues grokking FsCheck
following my previous question.
With a lot of SO help I now got the following code to define and register two custom data generators of my domain:
let genString15 =
Gen.sized (fun s -> Gen.resize (min s 15) Arb.generate<NonNull<string>>)
|> Gen.map (fun (NonNull str) -> str)
let genNonNegativeof f = gen {
let! (NonNegativeInt n) = Arb.generate<NonNegativeInt>
return (f n)
}
let genNonLegendaryItem = gen {
let! name = Gen.map Name genString15
let! quality = genNonNegativeof Quality
let! shelflife = genNonNegativeof Days
let! style = Gen.elements [Plain; Conjured]
return {
Name = name
Quality = quality
ShelfLife = shelflife
Style = style
}
}
let genLegendaryItem = genNonLegendaryItem |> Gen.map (fun item -> {item with Style = Legendary})
type NonLegendaryItem = NonLegendaryItem of Item
type LegendaryItem = LegendaryItem of Item
type Generators =
static member NonLegendaryItem() =
Gen.map NonLegendaryItem genNonLegendaryItem
static member LegendaryItem() =
Gen.map LegendaryItem genLegendaryItem
Arb.register<Generators>()
What I am trying now is to use those generators for my test case(s) using xUnit.Net (assume I’ve opened all the necessary libraries and the following handleDayOver: Int -> Item -> Item
, where Item
is also already defined and the function itself has been Example-based unit tested and is correct):
[<Property>]
let ``Some descriptive name``(item: NonLegendaryItem) =
let nli = handleDayOver 100 item
nli.Quality = Quality 0
This snippet won’t compile since item
is indeed NonLegendaryItem
whereas the function takes a “simple” Item
.
Trying this instead:
[<Property>]
let ``Some descriptive name`` (NonLegendaryItem item) =
let nli = handleDayOver 100 item
nli.Quality = Quality 0
Fails in the sense that now item
is not NonLegendaryItem
but a “simple” Item
and thus it may be of Style
s that invalidate the invariant (i.e. Legendary
that never drops to 0).
I don’t want to change my implementation of handleDayOver
since the (Non)LegendaryItem types are pure testing related with no bearing on the actual application, but I can’t figure out how to use them so that the test item is forced as a (Non)LegendaryItem and compiles without a type-error?
Thanks!