From 349c9f13c9bc6f7ae0e9fd1b64366f1f2ab42f12 Mon Sep 17 00:00:00 2001 From: Adam Becker Date: Sun, 7 Feb 2021 22:34:39 +0000 Subject: [PATCH] Add property args structure. --- src/Hedgehog/Hedgehog.fsproj | 1 + src/Hedgehog/Property.fs | 53 +++++++++++++++++++++++------------- src/Hedgehog/PropertyArgs.fs | 16 +++++++++++ src/Hedgehog/Report.fs | 25 ++++++++++++++--- 4 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 src/Hedgehog/PropertyArgs.fs diff --git a/src/Hedgehog/Hedgehog.fsproj b/src/Hedgehog/Hedgehog.fsproj index f5923a63..f94d0b79 100644 --- a/src/Hedgehog/Hedgehog.fsproj +++ b/src/Hedgehog/Hedgehog.fsproj @@ -41,6 +41,7 @@ https://github.com/hedgehogqa/fsharp-hedgehog/blob/master/doc/index.md + diff --git a/src/Hedgehog/Property.fs b/src/Hedgehog/Property.fs index c59bdfaf..dfa2550a 100644 --- a/src/Hedgehog/Property.fs +++ b/src/Hedgehog/Property.fs @@ -99,21 +99,19 @@ module Property = // let rec private takeSmallest - (renderRecheck : bool) - (size : Size) - (seed : Seed) + (args : PropertyArgs) (Node ((journal, x), xs) : Tree>) (nshrinks : int) (shrinkLimit : int Option) : Status = let failed = Failed { - Size = size - Seed = seed + Size = args.Size + Seed = args.Seed Shrinks = nshrinks Journal = journal - RenderRecheck = renderRecheck + RecheckType = args.RecheckType } - let takeSmallest tree = takeSmallest renderRecheck size seed tree (nshrinks + 1) shrinkLimit + let takeSmallest tree = takeSmallest args tree (nshrinks + 1) shrinkLimit match x with | Failure -> match Seq.tryFind (Outcome.isFailure << snd << Tree.outcome) xs with @@ -130,7 +128,7 @@ module Property = | Success _ -> OK - let private reportWith' (renderRecheck : bool) (size0 : Size) (seed : Seed) (config : PropertyConfig) (p : Property) : Report = + let private reportWith' (args : PropertyArgs) (config : PropertyConfig) (p : Property) : Report = let random = toGen p |> Gen.toRandom let nextSize size = @@ -139,7 +137,7 @@ module Property = else size + 1 - let rec loop seed size tests discards = + let rec loop args tests discards = if tests = config.TestLimit then { Tests = tests Discards = discards @@ -149,24 +147,29 @@ module Property = Discards = discards Status = GaveUp } else - let seed1, seed2 = Seed.split seed - let result = Random.run seed1 size random + let seed1, seed2 = Seed.split args.Seed + let result = Random.run seed1 args.Size random + let nextArgs = { + args with + Seed = seed2 + Size = nextSize args.Size + } match snd (Tree.outcome result) with | Failure -> { Tests = tests + 1 Discards = discards - Status = takeSmallest renderRecheck size seed result 0 config.ShrinkLimit} + Status = takeSmallest args result 0 config.ShrinkLimit} | Success () -> - loop seed2 (nextSize size) (tests + 1) discards + loop nextArgs (tests + 1) discards | Discard -> - loop seed2 (nextSize size) tests (discards + 1) + loop nextArgs tests (discards + 1) - loop seed size0 0 0 + loop args 0 0 let reportWith (config : PropertyConfig) (p : Property) : Report = - let seed = Seed.random () - p |> reportWith' true 1 seed config + let args = PropertyArgs.init + p |> reportWith' args config let report (p : Property) : Report = p |> reportWith PropertyConfig.defaultConfig @@ -201,10 +204,22 @@ module Property = | _ -> failure let reportRecheckWith (size : Size) (seed : Seed) (config : PropertyConfig) (p : Property) : Report = - reportWith' false size seed config p + let args = { + PropertyArgs.init with + RecheckType = RecheckType.None + Seed = seed + Size = size + } + reportWith' args config p let reportRecheck (size : Size) (seed : Seed) (p : Property) : Report = - reportWith' false size seed PropertyConfig.defaultConfig p + let args = { + PropertyArgs.init with + RecheckType = RecheckType.None + Seed = seed + Size = size + } + reportWith' args PropertyConfig.defaultConfig p let reportRecheckBoolWith (size : Size) (seed : Seed) (config : PropertyConfig) (p : Property) : Report = p |> bind ofBool |> reportRecheckWith size seed config diff --git a/src/Hedgehog/PropertyArgs.fs b/src/Hedgehog/PropertyArgs.fs new file mode 100644 index 00000000..7a7867ac --- /dev/null +++ b/src/Hedgehog/PropertyArgs.fs @@ -0,0 +1,16 @@ +namespace Hedgehog + +[] +type PropertyArgs = private { + RecheckType : RecheckType + Size : Size + Seed : Seed +} + +module PropertyArgs = + + let init = { + RecheckType = RecheckType.FSharp + Size = 0 + Seed = Seed.random () + } diff --git a/src/Hedgehog/Report.fs b/src/Hedgehog/Report.fs index 8ea85ab5..a551d898 100644 --- a/src/Hedgehog/Report.fs +++ b/src/Hedgehog/Report.fs @@ -4,12 +4,18 @@ namespace Hedgehog [] type discards [] type shrinks +[] +type RecheckType = + | None + | CSharp + | FSharp + type FailureData = { Size : Size Seed : Seed Shrinks : int Journal : Journal - RenderRecheck : bool + RecheckType : RecheckType } type Status = @@ -80,14 +86,25 @@ module Report = Seq.iter (appendLine sb) (Journal.eval failure.Journal) - if failure.RenderRecheck then + match failure.RecheckType with + | RecheckType.None -> + () + + | RecheckType.FSharp -> + appendLinef sb "This failure can be reproduced by running:" + appendLinef sb "> Property.recheck %d ({ Value = %A; Gamma = %A }) " + failure.Size + failure.Seed.Value + failure.Seed.Gamma + + | RecheckType.CSharp -> appendLinef sb "This failure can be reproduced by running:" - appendLinef sb "> Property.recheck (%d : Size) ({ Value = %A; Gamma = %A }) " + appendLinef sb "> property.Recheck(%d, new Seed { Value = %A; Gamma = %A })" failure.Size failure.Seed.Value failure.Seed.Gamma - sb.ToString (0, sb.Length - 1) // Exclude extra newline. + sb.ToString().Trim() // Exclude extra newline. let render (report : Report) : string = match report.Status with