在FsCheck中将两个生成器组合为单个任意一个

时间:2017-07-06 10:00:51

标签: c# fscheck property-based-testing

我想要在Stuff的集合上测试一个属性,其中Stuff之一满足某个属性。我有办法生成满足属性的Stuff,以及生成不属于Stuff的方法。

今天,我正在做这样的事情(是的,我在C#中使用FsCheck):

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

但是这感觉很笨拙和令人费解。是否有更简单和/或更惯用的方法来实现同样的事情,即测试两个仲裁产出的笛卡尔积?

1 个答案:

答案 0 :(得分:0)

您可以使用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 => { ... })