防止FsCheck产生NaN和无穷大

pha*_*haz 3 testing floating-point f# generator fscheck

我有一个深层嵌套的数据结构,到处都有浮点数.我正在使用FsCheck检查序列化然后反序列化后数据是否未更改.

当float为NaN或+/-无穷大时,此属性失败,但是,这种情况对我不感兴趣,因为我不希望这些值出现在实际数据中.

有没有办法防止FsCheck产生NaN和无穷大?

我已经尝试丢弃包含所述值的生成数据,但是这使得测试非常慢,实际上很慢,在我写这篇文章时测试仍在运行,我怀疑它实际上会完成...

Kur*_*out 9

对于包含浮点数的反射生成类型(我怀疑您正在使用),您可以通过编写类来覆盖浮点数的默认生成器,如下所示:

type Overrides() =
    static member Float() =
        Arb.Default.Float()
        |> filter (fun f -> not <| System.Double.IsNaN(f) &&
                            not <| System.Double.IsInfinity(f)) 
Run Code Online (Sandbox Code Playgroud)

然后打电话:

Arb.register<Overrides>()
Run Code Online (Sandbox Code Playgroud)

在FsCheck尝试生成类型之前; 例如,在您的测试设置中或在调用Check.Quick之前.

您可以检查register方法的结果,看看它如何将默认的任意实例与新的实例合并; 它应该覆盖它们.

如果您使用的是xUnit扩展,则可以使用PropertyAttribute的Arbitraries参数来避免调用Arb.register:

[<Property(Arbitraries=Overides)>]
Run Code Online (Sandbox Code Playgroud)


小智 6

正如Mauricio Scheffer所说,您可以在test参数中使用NormalFloat类型.

浮点列表的简单示例:

open FsCheck

let f (x : float list) = x |> List.map id

let propFloat (x : float list) = x = (f x)

let propNormalFloat (xn : NormalFloat list) = 
    let x = xn |> List.map NormalFloat.get
    x = f x

Check.Quick propFloat
//Falsifiable, after 18 tests (13 shrinks) (StdGen (761688149,295892075)):
//[nan]

Check.Quick propNormalFloat
//Ok, passed 100 tests.
Run Code Online (Sandbox Code Playgroud)