Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A way to render a list completely in the report? #323

Closed
altxt opened this issue Mar 1, 2021 · 2 comments · Fixed by #324
Closed

A way to render a list completely in the report? #323

altxt opened this issue Mar 1, 2021 · 2 comments · Fixed by #324
Milestone

Comments

@altxt
Copy link
Contributor

altxt commented Mar 1, 2021

Given a property that takes a list generator, such as this

[Test]
public void Hedgehog_List_IsPrintedIncomplete()
{
    var property =
        from xs in Property.ForAll(Gen.Int32(Range.Constant(1, 255)).List(Range.Constant(1, 100)))
        select xs.All(x => x < 255);
    property.Check(PropertyConfig.Default.WithShrinks(0));
}

When the property fails, the output only shows the first several elements of the list

System.Exception : *** Failed! Falsifiable (after 5 tests):
seq [188; 144; 215; 37; ...]

It can be beneficial to be able to see all elements of the list in the test output. This can be achieved by wrapping the input in a class and overriding its ToString(), but it takes significantly more code, so a simpler way would be preferable.

class Wrapper
{
    public List<int> Xs;

    public override string ToString()
    {
        return $"[{string.Join(", ", Xs)}]";
    }
}

[Test]
public void Hedgehog_ListWithinClassWithACustomToString_IsPrintedComplete()
{
    var gen =
        from xs in Gen.Int32(Range.Constant(1, 255)).List(Range.Constant(1, 100))
        select new Wrapper {Xs = xs};
    var property =
        from wrapper in Property.ForAll(gen)
        select wrapper.Xs.All(x => x < 255);
    property.Check(PropertyConfig.Default.WithShrinks(0));
}
@altxt
Copy link
Contributor Author

altxt commented Mar 2, 2021

An equivalent F# test works as expected

testCase "generated input list of five elements is not abbreviated in the report" <| fun _ ->
    Expect.throwsC
        (fun () ->
            property {
                let! xs = Range.singleton 0 |> Gen.int |> Gen.list (Range.singleton 5)
                return Seq.forall ((>) 0) xs
            }
            |> Property.checkWith (PropertyConfig.withShrinks 0<shrinks> PropertyConfig.defaultConfig)
        )
        (fun ex ->
            Expect.isNotMatch ex.Message "\.\.\." "Abbreviation (...) found"
        )

But if we convert the F# list to a C# list, like Hedgehog.Linq does, then the ellipsis is there

                let! xs = Range.singleton 0 |> Gen.int |> Gen.list (Range.singleton 5) |> Gen.map ResizeArray

It looks like sprintf "%A" only recognizes a C# generic List<T> (aka ResizeArray<_>) as IEnumerable (aka seq) but not as a list and so, knowing that it can be infinite or slow to traverse, decides to only dump the first elements.

@ghost
Copy link

ghost commented Mar 21, 2021

@altxt If you have more tests like these, we'd be glad to include them for the C# interface so we don't introduce regressions. C# support is something we definitely want to improve, so these would be a very welcome addition!

@ghost ghost added this to the 0.11.0 milestone Mar 24, 2021
@ghost ghost closed this as completed in #324 Mar 24, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant