【问题标题】:In FsCheck, how to generate a test record with non-negative fields?在 FsCheck 中,如何生成非负字段的测试记录?
【发布时间】:2011-11-16 23:53:56
【问题描述】:

在 F# 中,我有一个包含几个字段的记录:

    type myRecord = { a:float; b:float; c:float }

我正在使用 FsCheck 来测试一些使用此记录的属性。 对于(人为的)示例,

    let verify_this_property (r:myRecord) = myFunction(r) = (r.a * r.b) / r.c

由于 myFunction 的内部实现限制,我想让 FsCheck 创建测试用例,其中每个字段 a、b、c 都限制为非负浮点数。

我怀疑这需要为 myRecord 创建一个生成器,但我找不到任何示例说明如何执行此操作。

谁能提供指导?

【问题讨论】:

  • 你仔细阅读this FsCheck Wiki page了吗?它有一个如何编写和注册生成器的示例。
  • @fmr--是的,我已经仔细阅读了所有 FsCheck Wiki 页面。虽然提供了编写简单生成器的步骤(不是很清楚恕我直言),但我无法确定如何扩展它以创建记录生成器——因此,SO 问题。

标签: f# fscheck


【解决方案1】:

试试这个:

type Generators = 
    static member arbMyRecord =
        fun (a,b,c) -> { myRecord.a = a; b = b; c = c }
        <!> (Arb.generate<float> |> Gen.suchThat ((<) 0.) |> Gen.three)
        |> Arb.fromGen

Arb.register<Generators>() |> ignore
Check.Quick verify_this_property

&lt;!&gt; 是一个中缀map,对于应用风格很有用。这是一个等效的生成器:

type Generators = 
    static member arbMyRecord =
        Arb.generate<float> 
        |> Gen.suchThat ((<) 0.) 
        |> Gen.three
        |> Gen.map (fun (a,b,c) -> { myRecord.a = a; b = b; c = c })
        |> Arb.fromGen

如果你不想全局注册你的生成器,可以使用forAll

Check.Quick (forAll Generators.arbMyRecord verify_this_property)

作为练习向左收缩;)

【讨论】:

  • “”结构的含义是什么?我以前没见过。
  • @DavidH :它是一个中缀map,对于应用风格很有用。见bugsquash.blogspot.com/2010/12/…
  • @DavidH :解释更多。
  • forAll 住在哪里?好像没找到
  • @Maslow 和其他寻找这个的人:forAll 住在 Prop 模块中。另外,Gen.suchAt 似乎已被弃用,应该改用wherefilter
【解决方案2】:

您可以避免使用FsCheck conditional properties创建自定义生成器

let verify_this_property (r:myRecord) =
    (r.a > 0.0 && r.b > 0.0 && r.c > 0.0) ==> lazy (myFunction r = (r.a * r.b) * r.c)

虽然这会导致(基本上?)测试执行速度变慢,因为 FsCheck 将不得不丢弃所有不合适的测试条目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 2014-11-02
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 2012-10-05
    相关资源
    最近更新 更多