Объединение двух генераторов в один произвольный в FsCheck

У меня есть свойство, которое я хочу протестировать на наборе Stuff, где одно из Stuff удовлетворяет определенному свойству. У меня есть способ сгенерировать Stuff, удовлетворяющий свойству, и способ сгенерировать Stuff, который не удовлетворяет.

Сегодня я делаю что-то вроде этого (да, я использую FsCheck в 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();
}

но это жестко кодирует порядок, т. е. какой Stuff в коллекции удовлетворяет свойству; Я бы хотел, чтобы арбитраж это, а также.

Один из способов сделать это — вложить Prop.ForAll вызовов; внешний, который генерирует что-то, что определяет порядок, и внутренний, тот, который у меня есть выше, но передает параметр, управляющий порядком, сборщику коллекции:

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();
}

Но это кажется неуклюжим и запутанным. Есть ли более простой и/или более идиоматический способ добиться того же самого, т. е. проверить декартово произведение результатов двух произвольных значений?


person Tomas Aschan    schedule 06.07.2017    source источник


Ответы (1)


Вы можете использовать Gen.Shuffle для создания последовательностей в разном порядке:

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

потом

Prop.ForAll(gen, collection => { ... })
person Lee    schedule 06.07.2017