2

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?

Tomas Aschan
  • 53,075
  • 51
  • 214
  • 362

1 Answers1

0

You can use Gen.Shuffle to generate sequences in different orders:

var gen = from input in Gen.Choose(1, 5)
          let sc = GetStuffCollection(input)
          from shuffled in Gen.Shuffle(sc)
          select shuffled

then

Prop.ForAll(gen, collection => { ... })
Lee
  • 133,981
  • 18
  • 209
  • 268