5

我有一个深度嵌套的数据结构,到处都是浮点数。我正在使用 FsCheck 来检查序列化然后反序列化后数据是否不变。

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

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

我曾尝试丢弃包含所述值的生成数据,但这会使测试变得异常缓慢,事实上如此缓慢,以至于在我写这篇文章时测试仍在运行,我怀疑它是否会真正完成......

4

2 回答 2

10

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

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)>]
于 2014-07-30T15:32:57.600 回答
8

正如 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.
于 2014-07-30T15:30:13.597 回答