3

I have a function that should get two actual params for testing. Both values shall be created by Arbitrary instances as they need to be of some well formdness that cant be totally arbitrary.
So I create the following code

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

But how do I now combine those 2 Arbitrary instances so that they match up with the signature of test method?

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

Check.QuickThrowOnFailure prop
robkuz
  • 9,488
  • 5
  • 29
  • 50

1 Answers1

6

Given two types, SomeTypeA and SomeTypeB:

type SomeTypeA = 
    { A : obj }

type SomeTypeB = 
    { B : obj }

You can create a Property, where the input is those two types, like so:

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'.

You also need to take care, that the signature of the testing method now reflects the created Arbitrary - becoming a (uncurried) function on pairs.

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

How the example works:

  • The gen computation expression creates a generator of type Gen<SomeTypeA * SomeTypeB>
  • An Arbitrary<SomeTypeA * SomeTypeB> instance is created from that generator
  • Finally, a (QuickCheck/FsCheck) property is created from the arbitrary via Prop.forAll

It's always the same path:

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

Hope that helps.

Nikos Baxevanis
  • 10,868
  • 2
  • 46
  • 80