FsCheck:如何生成依赖于其他测试数据的测试数据?

Posted

技术标签:

【中文标题】FsCheck:如何生成依赖于其他测试数据的测试数据?【英文标题】:FsCheck: How to generate test data that depends on other test data? 【发布时间】:2018-03-31 20:43:33 【问题描述】:

FsCheck 有一些简洁的默认Arbitrary 类型来生成测试数据。但是,如果我的某个考试日期取决于另一个考试日期怎么办?

例如,考虑string.Substring() 的属性,即生成的子字符串永远不会比输入字符串长:

[Fact]
public void SubstringIsNeverLongerThanInputString()

    Prop.ForAll(
        Arb.Default.NonEmptyString(),
        Arb.Default.PositiveInt(),
        (input, length) => input.Get.Substring(0, length.Get).Length <= input.Get.Length
    ).QuickCheckThrowOnFailure();

虽然Substring 的实现肯定是正确的,但这个属性失败了,因为最终会生成一个比生成的NonEmptyString 更长的PositiveInt,从而导致异常。

收缩:NonEmptyString "a" PositiveInt 2 异常:System.ArgumentOutOfRangeException:索引和长度必须引用字符串中的位置。

我可以保护与 if (input.Length &lt; length) return true; 的比较,但这样我最终会进行大量测试运行,甚至没有检查该属性。

如何告诉 FsCheck 只生成不超过输入字符串的PositiveInts?我想我必须使用 Gen&lt;T&gt; 类,但它的界面让我很困惑......我尝试了以下但仍然得到 PositiveInts 超过字符串:

var inputs = Arb.Default.NonEmptyString();
// I have no idea what I'm doing here...
var lengths = inputs.Generator.Select(s => s.Get.Length).ToArbitrary();

Prop.ForAll(
    inputs,
    lengths,
    (input, length) => input.Get.Substring(0, length).Length <= input.Get.Length
).QuickCheckThrowOnFailure();

【问题讨论】:

fscheck.github.io/FsCheck/TestData.html 我已经多次浏览了这个网站,但仍然无法找到一种方法来做我想做的事。 【参考方案1】:

您可以使用SelectMany 创建依赖于从另一个生成的值的生成器。这也允许您使用 LINQ 查询语法,例如

var gen = from s in Arb.Generate<NonEmptyString>()
          from i in Gen.Choose(0, s.Get.Length - 1)
          select Tuple.Create(s, i);

var p = Prop.ForAll(Arb.From(gen), t =>

    var s = t.Item1.Get;
    var len = t.Item2;
    return s.Substring(0, len).Length <= s.Length;
);

Check.Quick(p);

【讨论】:

这是我可以在official docs 中找到的吗?如果不能,请添加您的参考资料? @GoodNightNerdPride - 我认为我没有看到太多关于 C# 互操作的文档,所以我可能是根据阅读源代码和来自 gen 构建器的有根据的猜测发现的。 F# 计算表达式(如 gen ... )与 C# LINQ 查询语法非常接近,因为它们是从相同的语法模式构建的(尽管 F# 支持更多功能)。 文档中没有太多关于 F# 计算表达式或 LINQ 语法的示例。这是一个例子github.com/fscheck/FsCheck/blob/master/examples/… LINQ 在TestData 页面的第二段中提到,这里有一个小例子:fscheck.github.io/FsCheck/TestData.html#Generators

以上是关于FsCheck:如何生成依赖于其他测试数据的测试数据?的主要内容,如果未能解决你的问题,请参考以下文章

Expecto FsCheck在生成字符串时出现堆栈溢出异常

如果随机生成的输入没有用,我如何重新尝试基于属性的测试?

如何使FsCheck生成与MaxLengthAttribute相关的随机字符串?

依赖于数据库视图的集成测试

单元测试依赖于其他 getter 的 Vuex getter

如何测试依赖于具有关系的 Eloquent 模型的类?