I have a property I want to test on a collection of Stuff
, where one of the Stuff
satisfies a certain property. I have a way to generate a Stuff
satisfying the property, and a way to generate a Stuff
that doesn't.
Today, I'm doing something like this (yes, I'm using FsCheck in C#):
IEnumerable<Stuff> GetStuffCollection(int input)
{
yield return GenerateStuffSatisfyingProperty(input);
yield return GenerateStuffNotSatisfyingProperty(input);
}
[Fact]
public void PropertyForCollectionHolds()
{
Prop.ForAll(Arb.Choose(1,5), input =>
{
var collection = GetStuffCollection(input);
return collection.SatisfiesProperty();
}).VerboseCheckThrowOnFailure();
}
but this hard-codes the ordering, i.e. which Stuff
in the collection that satisfies the property; I'd like to arbitrate that as well.
One way to do it would be to nest Prop.ForAll
calls; an outer one that generates something that determines the ordering, and an inner one which is the one I have above but passing a parameter controlling ordering to the collection builder:
IEnumerable<Stuff> GetStuffCollection(int input, bool first)
{
if (first)
{
yield return GenerateStuffSatisfyingProperty(input);
yield return GenerateStuffNotSatisfyingProperty(input);
}
else
{
yield return GenerateStuffNotSatisfyingProperty(input);
yield return GenerateStuffSatisfyingProperty(input);
}
}
[Fact]
public void PropertyForCollectionHolds()
{
Prop.ForAll(Arb.Default.Bool(), first =>
Prop.ForAll(Arb.Choose(1,5), input =>
{
var collection = GetStuffCollection(input, first);
return collection.SatisfiesProperty();
}).VerboseCheckThrowOnFailure()
).VerboseCheckThrowOnFailure();
}
But this feels klunky and convoluted. Is there a simpler and/or more idiomatic way to achieve the same thing, i.e. testing the cartesian product of the output of two arbitraries?