unit-testing.net-coref#fscheck

How to force any decimal value (be it part of a type or not) generated with fscheck to be within a certain range?


I'm using fscheck to write some unite tests and I would like to narrow down the range of decimal automatically generated and that regardless of the parameter I'm passing. What I mean by that is that let's say I have the types below:

Without having something to define an arbitrary for each single type, just that down the line in the generation if there a decimal it must say be between 0 and 300,000.

module Tests

open Xunit
open FsCheck.Xunit
open Swensen.Unquote


let addDecimals a b: decimal =
   a + b

[<Property>]
let ``test adding two decimals`` a b =
    let actual = addDecimals a b
    let expected = a + b
    test<@ actual = expected @>

type DecimalHolder =
    { Value: decimal }

let addDecimalHolders a b =
    { Value = a.Value + b.Value }

[<Property>]
let ``test adding two decimal holders`` a b =
    let actual = addDecimalHolders a b
    let expected = { Value = a.Value + b.Value }
    test<@ actual = expected @>

type DecimalStuff =
    | Value of decimal
    | Holder of DecimalHolder
    | Holders of DecimalHolder list
    // Whatever

etc.

How can I achieve that?


Solution

  • Ok actually the Arbitrary definition works recursively across parameters types was enough:

    module Tests
    
    open Xunit
    open FsCheck.Xunit
    open Swensen.Unquote
    
    type NotBigPositiveDecimalArbitrary =
    
        static member NotBigPositiveDecimal() =
            Gen.choose (1, 500)
            |> Gen.map (fun x -> decimal x)
            |> Arb.fromGen
    
    let addDecimals a b: decimal =
       a + b
    
    [<Property(Arbitrary = [| typeof<NotBigPositiveDecimalArbitrary> |])>]
    let ``test adding two decimals`` a b =
        let actual = addDecimals a b
        let expected = a + b
        test<@ actual = expected @>
    
    type DecimalHolder =
        { Value: decimal }
    
    let addDecimalHolders a b =
        { Value = a.Value + b.Value }
    
    [<Property(Arbitrary = [| typeof<NotBigPositiveDecimalArbitrary> |])>]
    let ``test adding two decimal holders`` a b =
        let actual = addDecimalHolders a b
        let expected = { Value = a.Value + b.Value }
        test<@ actual = expected @>