防止FsCheck产生NaN和无穷大

时间:2014-07-30 00:21:56

标签: testing f# floating-point generator fscheck

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

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

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

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

2 个答案:

答案 0 :(得分:8)

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

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

然后致电:

Arb.register<Overrides>()

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

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

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

[<Property(Arbitraries=Overides)>]

答案 1 :(得分:6)

正如Mauricio Scheffer所说,你可以在测试参数中使用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.