【问题标题】:Preventing FsCheck from generating NaN and infinities防止 FsCheck 生成 NaN 和无穷大
【发布时间】:2014-09-21 12:19:45
【问题描述】:

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

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

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

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

【问题讨论】:

  • 哦,酷。那么,我该怎么做呢? :-)
  • 将您的测试参数设为NormalFloat
  • 对不起,我还是没听懂你想说什么。应该生成的数据是记录的记录(sorta),其中一些包含浮点数。我希望所有应该生成浮点数的地方都不要使用 NaN 或无穷大。
  • 您是为这些数据编写了自己的生成器,还是使用了内置的基于反射的生成器?

标签: testing f# floating-point generator fscheck


【解决方案1】:

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

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)>]

【讨论】:

  • 您是否介意在您的最后一段扩展一下,并举例说明如何做到这一点?
【解决方案2】:

正如 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.

【讨论】:

  • 我想这可能适用于其他情况,例如您所说明的情况。问题是,数据不仅仅是一个浮点数列表或类似的东西,它允许我将 NormalFloat 作为类型的一部分编写,而是一个更复杂的结构,它在各种地方都包含浮点数,而且还包含其他类型。我需要的是让 FsCheck 在任何需要浮点数的地方生成 NormalFloats,无论数据看起来如何,正如 Kurt Schelfthout 所示。 :-)
猜你喜欢
  • 2016-10-16
  • 2010-12-21
  • 2013-10-22
  • 2014-02-14
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
  • 2012-04-03
相关资源
最近更新 更多