我有一个深度嵌套的数据结构,到处都是浮点数。我正在使用 FsCheck 来检查序列化然后反序列化后数据是否不变。
当浮点数为 NaN 或 +/- 无穷大时,此属性会失败,但是,我对这种情况不感兴趣,因为我不希望这些值出现在实际数据中。
有没有办法防止 FsCheck 生成 NaN 和无穷大?
我曾尝试丢弃包含所述值的生成数据,但这会使测试变得异常缓慢,事实上如此缓慢,以至于在我写这篇文章时测试仍在运行,我怀疑它是否会真正完成......
我有一个深度嵌套的数据结构,到处都是浮点数。我正在使用 FsCheck 来检查序列化然后反序列化后数据是否不变。
当浮点数为 NaN 或 +/- 无穷大时,此属性会失败,但是,我对这种情况不感兴趣,因为我不希望这些值出现在实际数据中。
有没有办法防止 FsCheck 生成 NaN 和无穷大?
我曾尝试丢弃包含所述值的生成数据,但这会使测试变得异常缓慢,事实上如此缓慢,以至于在我写这篇文章时测试仍在运行,我怀疑它是否会真正完成......
对于包含浮点数的反射生成类型(我怀疑您正在使用),您可以通过编写如下类来覆盖浮点数的默认生成器:
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)>]
正如 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.