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

daizhj 阅读:13 2024-09-07 23:24:14 评论:0

我有一个函数应该获取两个实际参数进行测试。 这两个值都应由 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> 

希望对您有所帮助。


标签:测试
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号