f# - 如何组合 2 个任意实例以匹配测试方法签名

标签 f# fscheck

我有一个函数应该获取两个实际参数进行测试。 这两个值都应由 Arbitrary 实例创建,因为它们需要具有某种不能完全任意的良好格式。
所以我创建了以下代码

let updating (x:SomeType) (y:SomeOtherType) =
    let result = update x y
    result.someProp = x.someProp
    && result.otherProp = y.otherProp

let arbSomeType = 
    Arb.generate<SomeType> 
        |> Gen.filter fun x -> x.checkSomeStuff
        |> Arb.fromGen

let arbSomeType = 
    Arb.generate<SomeOtherType> 
        |> Gen.filter fun x -> x.checkPropertiesOfThis
        |> Arb.fromGen

但是我现在如何组合这 2 个 Arbitrary 实例,以便它们与测试方法的签名相匹配?

//let prop = Prop.forAll arbSomeType + arbSomeType updating

Check.QuickThrowOnFailure prop

最佳答案

给定两种类型,SomeTypeASomeTypeB :

type SomeTypeA = 
    { A : obj }

type SomeTypeB = 
    { B : obj }

您可以创建一个 Property ,其中输入是这两种类型,如下所示:

let prop =
    gen { let! a = Arb.generate<SomeTypeA>
          let! b = Arb.generate<SomeTypeB>
          return a, b }
    |> Arb.fromGen
    |> Prop.forAll
    <| fun (a, b) ->
        // 'a' is SomeTypeA
        // 'b' is SomeTypeB
        true // Dummy - replace with whatever you want to do with 'a' and 'b'.

您还需要注意,测试方法的签名现在反射(reflect)了创建的 Arbitrary - 成为成对的(未柯里化(Currying)的)函数。

// instead of
let updating (x:SomeType) (y:SomeOtherType) = ...
// do this
let updating (x:SomeType, y:SomeOtherType) = ...

示例的工作原理:

  • gen计算表达式创建类型为 Gen<SomeTypeA * SomeTypeB> 的生成器
  • Arbitrary<SomeTypeA * SomeTypeB>实例是从该生成器创建的
  • 最后,通过 Prop.forAll 从任意项创建一个 (QuickCheck/FsCheck) 属性

总是相同的路径:

Generator[/optional Shrinker] -> Arbitrary -> Property -> <your_code>

希望对您有所帮助。

关于f# - 如何组合 2 个任意实例以匹配测试方法签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39895446/

相关文章:

f# - 为什么尾递归函数对于正常递归函数成功执行的输入失败?

f# - 在 HtmlProvider<...>.Table.Row> 中自动输入列

types - F#在模式匹配中返回不同的类型

f# - 是否可以在无需将测试代码标记为内部的情况下测试内部代码?

c# - 是否有 Hilbert-Huang 变换的 .Net(首选 F# 或 C#)实现?

unit-testing - 使用 RGR 方法时,属性测试是否应该与单元测试一起运行?

c# - 在 FsCheck 中将两个生成器组合成一个任意生成器

f# - 使用 FSCheck 生成器

f# - F# 中的累加器生成器