使用 FsCheck,我在测试中得到不同的结果,一次 100% 通过,另一个时间错误



我创建了一个生成器来生成具有相同长度的int列表,并测试zip和解压缩的属性。运行测试我偶尔收到错误

错误:System.ArgumentException:list2 比 list1 短 1 个元素

但这不应该因为我的发电机而发生。

我得到了三倍的测试100%通过,然后是上面的错误。为什么?似乎我的发电机无法正常工作。

let samelength (x, y) = 
    List.length x = List.length y
let arbMyGen2 = Arb.filter samelength Arb.from<int list * int list> 
type MyGenZ =
    static member genZip() = 
       {
        new Arbitrary<int list * int list>() with
            override x.Generator = arbMyGen2 |> Arb.toGen
            override x.Shrinker t = Seq.empty
    }
let _ = Arb.register<MyGenZ>()
let pro_zip (xs: int list, ys: int list) = 
   (xs, ys) = List.unzip(List.zip xs ys)
   |> Prop.collect (List.length xs = List.length ys)
do Check.Quick pro_zip

你的代码,正如所写的,对我有用。所以我不确定到底出了什么问题,但我可以给你一些有用的(希望是!(提示。

首先,尽量不使用注册机制,而是使用 Prop.forAll ,如下所示:

let pro_zip  = 
   Prop.forAll arbMyGen2 (fun (xs,ys) ->
        (xs, ys) = List.unzip(List.zip xs ys)
        |> Prop.collect (List.length xs))
do Check.Quick pro_zip

请注意,我还更改了Prop.collect调用以收集列表的长度,这提供了更有趣的输出。事实上,您的属性已经检查列表的长度是否相同(尽管是隐式的(,因此如果不是,测试将失败并显示反例。

Arb.filter将现有Arbitrary(即生成器过滤器(转换为新Arbitrary。换句话说,arbMyGen2有一个可以工作的收缩函数(即只返回长度相等的较小列表对(,而genZip()你扔掉收缩器。简单地写就好

type MyGenZ =
    static member genZip() = arbMyGen2

相反。

最新更新