From cf24ac361bd48f410f21ece57d0b6c016537e449 Mon Sep 17 00:00:00 2001 From: Alex T Date: Wed, 3 Mar 2021 01:23:10 +0500 Subject: [PATCH 1/7] Special processing for printing ResizeArray<_> in Property.forAll #323 --- src/Hedgehog/Property.fs | 18 +++++++++++++++++- tests/Hedgehog.Tests/Hedgehog.Tests.fsproj | 1 + tests/Hedgehog.Tests/Program.fs | 1 + tests/Hedgehog.Tests/PropertyTests.fs | 21 +++++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/Hedgehog.Tests/PropertyTests.fs diff --git a/src/Hedgehog/Property.fs b/src/Hedgehog/Property.fs index 76191f28..3557f7d7 100644 --- a/src/Hedgehog/Property.fs +++ b/src/Hedgehog/Property.fs @@ -81,11 +81,27 @@ module Property = let bind (k : 'a -> Property<'b>) (m : Property<'a>) : Property<'b> = bindGen (toGen << k) (toGen m) |> ofGen + let private (|IsGenericList|_|) (candidate : obj) : seq option = + let t = candidate.GetType() + // have to use TypeInfo due to targeting netstandard 1.6 + let t = System.Reflection.IntrospectionExtensions.GetTypeInfo(t) + let isList = t.IsGenericType && t.GetGenericTypeDefinition() = typedefof> + if isList + then Some (candidate :?> System.Collections.IEnumerable |> Seq.cast) + else None + + let private printValue (value) : string = + match value with + | IsGenericList list -> + let printedElements = Seq.map (fun element -> sprintf "%A" element) list + "[" + (String.concat ", " printedElements) + "]" + | _ -> sprintf "%A" value + let forAll (k : 'a -> Property<'b>) (gen : Gen<'a>) : Property<'b> = let handle (e : exn) = Gen.constant (Journal.singletonMessage (string e), Failure) |> ofGen let prepend (x : 'a) = - counterexample (fun () -> sprintf "%A" x) + counterexample (fun () -> printValue x) |> bind (fun _ -> try k x with e -> handle e) |> toGen diff --git a/tests/Hedgehog.Tests/Hedgehog.Tests.fsproj b/tests/Hedgehog.Tests/Hedgehog.Tests.fsproj index 2e83d781..b058080a 100644 --- a/tests/Hedgehog.Tests/Hedgehog.Tests.fsproj +++ b/tests/Hedgehog.Tests/Hedgehog.Tests.fsproj @@ -16,6 +16,7 @@ + diff --git a/tests/Hedgehog.Tests/Program.fs b/tests/Hedgehog.Tests/Program.fs index e7be2b49..f28abfce 100644 --- a/tests/Hedgehog.Tests/Program.fs +++ b/tests/Hedgehog.Tests/Program.fs @@ -13,6 +13,7 @@ let allTests = testList "All tests" [ SeedTests.seedTests ShrinkTests.shrinkTests MinimalTests.minimalTests + PropertyTests.propertyTests ] [] diff --git a/tests/Hedgehog.Tests/PropertyTests.fs b/tests/Hedgehog.Tests/PropertyTests.fs new file mode 100644 index 00000000..2da00c48 --- /dev/null +++ b/tests/Hedgehog.Tests/PropertyTests.fs @@ -0,0 +1,21 @@ +module Hedgehog.Tests.PropertyTests + +open Hedgehog +open Expecto +open TestDsl + +let propertyTests = testList "Property tests" [ + testCase "generated C# list of five elements is not abbreviated in the failure report" <| fun _ -> + Expect.throwsC + (fun () -> + property { + let! xs = Range.singleton 0 |> Gen.int |> Gen.list (Range.singleton 5) |> Gen.map ResizeArray + return Seq.forall ((>) 0) xs + } + |> Property.checkWith (PropertyConfig.withShrinks 0 PropertyConfig.defaultConfig) + ) + (fun ex -> + Expect.isNotMatch ex.Message "\.\.\." "Abbreviation (...) found" + ) + +] From 620576ff294076c7773da4e482334e41222830b0 Mon Sep 17 00:00:00 2001 From: Alex T Date: Wed, 3 Mar 2021 01:47:58 +0500 Subject: [PATCH 2/7] Disabled reflection-based processing for Fable --- src/Hedgehog/Property.fs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Hedgehog/Property.fs b/src/Hedgehog/Property.fs index 3557f7d7..c6ab982b 100644 --- a/src/Hedgehog/Property.fs +++ b/src/Hedgehog/Property.fs @@ -81,6 +81,7 @@ module Property = let bind (k : 'a -> Property<'b>) (m : Property<'a>) : Property<'b> = bindGen (toGen << k) (toGen m) |> ofGen +#if !FABLE_COMPILER let private (|IsGenericList|_|) (candidate : obj) : seq option = let t = candidate.GetType() // have to use TypeInfo due to targeting netstandard 1.6 @@ -96,6 +97,10 @@ module Property = let printedElements = Seq.map (fun element -> sprintf "%A" element) list "[" + (String.concat ", " printedElements) + "]" | _ -> sprintf "%A" value +#else + let private printValue (value) : string = + sprintf "%A" value +#endif let forAll (k : 'a -> Property<'b>) (gen : Gen<'a>) : Property<'b> = let handle (e : exn) = From 73b443738a85336b27f4e76183c267f3337b6931 Mon Sep 17 00:00:00 2001 From: Alex T Date: Wed, 3 Mar 2021 01:54:28 +0500 Subject: [PATCH 3/7] Disabled the test for Fable --- tests/Hedgehog.Tests/PropertyTests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Hedgehog.Tests/PropertyTests.fs b/tests/Hedgehog.Tests/PropertyTests.fs index 2da00c48..45e13f3a 100644 --- a/tests/Hedgehog.Tests/PropertyTests.fs +++ b/tests/Hedgehog.Tests/PropertyTests.fs @@ -5,7 +5,7 @@ open Expecto open TestDsl let propertyTests = testList "Property tests" [ - testCase "generated C# list of five elements is not abbreviated in the failure report" <| fun _ -> + fableIgnore "generated C# list of five elements is not abbreviated in the failure report" <| fun _ -> Expect.throwsC (fun () -> property { From c6f1742f7dd4f7cca59e3be7eaff6ff5a228cc72 Mon Sep 17 00:00:00 2001 From: Alex T Date: Wed, 3 Mar 2021 03:27:55 +0500 Subject: [PATCH 4/7] Applied changes recommended in review --- src/Hedgehog/Property.fs | 16 +++++++--------- tests/Hedgehog.Tests/PropertyTests.fs | 17 ++++++----------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Hedgehog/Property.fs b/src/Hedgehog/Property.fs index c6ab982b..3cab49dc 100644 --- a/src/Hedgehog/Property.fs +++ b/src/Hedgehog/Property.fs @@ -81,25 +81,23 @@ module Property = let bind (k : 'a -> Property<'b>) (m : Property<'a>) : Property<'b> = bindGen (toGen << k) (toGen m) |> ofGen -#if !FABLE_COMPILER - let private (|IsGenericList|_|) (candidate : obj) : seq option = +#if FABLE_COMPILER + let private printValue (value) : string = + sprintf "%A" value +#else + let private (|IsResizeArray|_|) (candidate : obj) : obj list option = let t = candidate.GetType() // have to use TypeInfo due to targeting netstandard 1.6 let t = System.Reflection.IntrospectionExtensions.GetTypeInfo(t) let isList = t.IsGenericType && t.GetGenericTypeDefinition() = typedefof> if isList - then Some (candidate :?> System.Collections.IEnumerable |> Seq.cast) + then Some (candidate :?> System.Collections.IEnumerable |> Seq.cast |> List.ofSeq) else None let private printValue (value) : string = match value with - | IsGenericList list -> - let printedElements = Seq.map (fun element -> sprintf "%A" element) list - "[" + (String.concat ", " printedElements) + "]" + | IsResizeArray list -> sprintf "%A" list | _ -> sprintf "%A" value -#else - let private printValue (value) : string = - sprintf "%A" value #endif let forAll (k : 'a -> Property<'b>) (gen : Gen<'a>) : Property<'b> = diff --git a/tests/Hedgehog.Tests/PropertyTests.fs b/tests/Hedgehog.Tests/PropertyTests.fs index 45e13f3a..a4d7b8d3 100644 --- a/tests/Hedgehog.Tests/PropertyTests.fs +++ b/tests/Hedgehog.Tests/PropertyTests.fs @@ -6,16 +6,11 @@ open TestDsl let propertyTests = testList "Property tests" [ fableIgnore "generated C# list of five elements is not abbreviated in the failure report" <| fun _ -> - Expect.throwsC - (fun () -> - property { - let! xs = Range.singleton 0 |> Gen.int |> Gen.list (Range.singleton 5) |> Gen.map ResizeArray - return Seq.forall ((>) 0) xs - } - |> Property.checkWith (PropertyConfig.withShrinks 0 PropertyConfig.defaultConfig) - ) - (fun ex -> - Expect.isNotMatch ex.Message "\.\.\." "Abbreviation (...) found" - ) + let prop = property { + let! xs = Range.singleton 0 |> Gen.int |> Gen.list (Range.singleton 5) |> Gen.map ResizeArray + return false + } + let report = Property.renderWith (PropertyConfig.withShrinks 0 PropertyConfig.defaultConfig) prop + Expect.isNotMatch report "\.\.\." "Abbreviation (...) found" ] From bd7fe3922414b6660af5079ba834619450377c80 Mon Sep 17 00:00:00 2001 From: Alex T Date: Thu, 4 Mar 2021 01:24:57 +0500 Subject: [PATCH 5/7] Converted active pattern to regular function --- src/Hedgehog/Property.fs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Hedgehog/Property.fs b/src/Hedgehog/Property.fs index 3cab49dc..a308fe0e 100644 --- a/src/Hedgehog/Property.fs +++ b/src/Hedgehog/Property.fs @@ -81,24 +81,23 @@ module Property = let bind (k : 'a -> Property<'b>) (m : Property<'a>) : Property<'b> = bindGen (toGen << k) (toGen m) |> ofGen + + // sprintf "%A" is not prepared for printing ResizeArray<_> (C# List) so we prepare the value instead + let private prepareForPrinting (value: obj) : obj = #if FABLE_COMPILER - let private printValue (value) : string = - sprintf "%A" value + value #else - let private (|IsResizeArray|_|) (candidate : obj) : obj list option = - let t = candidate.GetType() + let t = value.GetType() // have to use TypeInfo due to targeting netstandard 1.6 let t = System.Reflection.IntrospectionExtensions.GetTypeInfo(t) let isList = t.IsGenericType && t.GetGenericTypeDefinition() = typedefof> if isList - then Some (candidate :?> System.Collections.IEnumerable |> Seq.cast |> List.ofSeq) - else None + then value :?> System.Collections.IEnumerable |> Seq.cast |> List.ofSeq :> obj + else value +#endif let private printValue (value) : string = - match value with - | IsResizeArray list -> sprintf "%A" list - | _ -> sprintf "%A" value -#endif + value |> prepareForPrinting |> sprintf "%A" let forAll (k : 'a -> Property<'b>) (gen : Gen<'a>) : Property<'b> = let handle (e : exn) = From 9262e69afb5e45433b9d4b8ff9fe4efafe57efa9 Mon Sep 17 00:00:00 2001 From: Alex T Date: Thu, 4 Mar 2021 22:41:40 +0500 Subject: [PATCH 6/7] Used forward pipe in test --- tests/Hedgehog.Tests/PropertyTests.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Hedgehog.Tests/PropertyTests.fs b/tests/Hedgehog.Tests/PropertyTests.fs index a4d7b8d3..c7ae1f6e 100644 --- a/tests/Hedgehog.Tests/PropertyTests.fs +++ b/tests/Hedgehog.Tests/PropertyTests.fs @@ -6,11 +6,11 @@ open TestDsl let propertyTests = testList "Property tests" [ fableIgnore "generated C# list of five elements is not abbreviated in the failure report" <| fun _ -> - let prop = property { + let report = (property { let! xs = Range.singleton 0 |> Gen.int |> Gen.list (Range.singleton 5) |> Gen.map ResizeArray return false } - let report = Property.renderWith (PropertyConfig.withShrinks 0 PropertyConfig.defaultConfig) prop + |> Property.renderWith (PropertyConfig.withShrinks 0 PropertyConfig.defaultConfig)) Expect.isNotMatch report "\.\.\." "Abbreviation (...) found" ] From 7424e90d27e023c10fd60c1cfa956062469d4a40 Mon Sep 17 00:00:00 2001 From: Alex T Date: Fri, 5 Mar 2021 01:41:17 +0500 Subject: [PATCH 7/7] Moved a helper function into the using function Replaced extra parentheses with indentation in test --- src/Hedgehog/Property.fs | 29 +++++++++++++-------------- tests/Hedgehog.Tests/PropertyTests.fs | 11 +++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Hedgehog/Property.fs b/src/Hedgehog/Property.fs index a308fe0e..a6f00394 100644 --- a/src/Hedgehog/Property.fs +++ b/src/Hedgehog/Property.fs @@ -81,22 +81,21 @@ module Property = let bind (k : 'a -> Property<'b>) (m : Property<'a>) : Property<'b> = bindGen (toGen << k) (toGen m) |> ofGen - - // sprintf "%A" is not prepared for printing ResizeArray<_> (C# List) so we prepare the value instead - let private prepareForPrinting (value: obj) : obj = -#if FABLE_COMPILER - value -#else - let t = value.GetType() - // have to use TypeInfo due to targeting netstandard 1.6 - let t = System.Reflection.IntrospectionExtensions.GetTypeInfo(t) - let isList = t.IsGenericType && t.GetGenericTypeDefinition() = typedefof> - if isList - then value :?> System.Collections.IEnumerable |> Seq.cast |> List.ofSeq :> obj - else value -#endif - let private printValue (value) : string = + // sprintf "%A" is not prepared for printing ResizeArray<_> (C# List) so we prepare the value instead + let prepareForPrinting (value: obj) : obj = + #if FABLE_COMPILER + value + #else + let t = value.GetType() + // have to use TypeInfo due to targeting netstandard 1.6 + let t = System.Reflection.IntrospectionExtensions.GetTypeInfo(t) + let isList = t.IsGenericType && t.GetGenericTypeDefinition() = typedefof> + if isList + then value :?> System.Collections.IEnumerable |> Seq.cast |> List.ofSeq :> obj + else value + #endif + value |> prepareForPrinting |> sprintf "%A" let forAll (k : 'a -> Property<'b>) (gen : Gen<'a>) : Property<'b> = diff --git a/tests/Hedgehog.Tests/PropertyTests.fs b/tests/Hedgehog.Tests/PropertyTests.fs index c7ae1f6e..4c52d7cc 100644 --- a/tests/Hedgehog.Tests/PropertyTests.fs +++ b/tests/Hedgehog.Tests/PropertyTests.fs @@ -6,11 +6,12 @@ open TestDsl let propertyTests = testList "Property tests" [ fableIgnore "generated C# list of five elements is not abbreviated in the failure report" <| fun _ -> - let report = (property { - let! xs = Range.singleton 0 |> Gen.int |> Gen.list (Range.singleton 5) |> Gen.map ResizeArray - return false - } - |> Property.renderWith (PropertyConfig.withShrinks 0 PropertyConfig.defaultConfig)) + let report = + property { + let! xs = Range.singleton 0 |> Gen.int |> Gen.list (Range.singleton 5) |> Gen.map ResizeArray + return false + } + |> Property.renderWith (PropertyConfig.withShrinks 0 PropertyConfig.defaultConfig) Expect.isNotMatch report "\.\.\." "Abbreviation (...) found" ]