vincent-hugot / qtest

Inline (Unit) Tests for OCaml
GNU General Public License v3.0
67 stars 8 forks source link

traceable QCheck.map #32

Closed edwintorok closed 8 years ago

edwintorok commented 8 years ago

When QCheck prints a counter-example it would be useful to get more information on why the property fails, to help debug the failure. Think of it as the difference between assert_bool and assert_equal in OUnit: assert_bool is great at finding bugs, assert_equal is great at providing a useful failure report.

Proposed:

val map' : ?print:'b Print.t -> 'a arbitrary -> ('a -> 'b) -> ('a * 'b) arbitrary
val map_hide : ?print:'b Print.t -> 'a arbitrary -> ('a -> 'b) -> 'b arbitrary

map' would use the specified printer, and the shrinkers/small/collect from 'a. This would probably require the same property for f as for QCheck.map ~rev.

map_hide is like map' (uses shrinker from 'a), except it doesn't store the input in the resulting arbitrary directly. Not sure if this is implementable at all with QCheck, the idea is that I could use map_hide to add some "tracing" to my value generation and when the final property test fails I could see all the intermediate results that were constructed that lead up to the failure.

Usecase: f1, f2 and f are the functions under test:

Test.make mygen (fun a -> compare (f1 a) (f2 a) = 0);
Test.make (pair mygen mygen) (fun a b -> compare a (f a b) <=  0)

When QCheck finds a bug and prints a counter-example it would be useful to know what f1 a and f2 b actually were, because it may not be easy to rerun these in utop (for example if I used QCheck.map ~rev a lot to build mygen, then QCheck would print some earlier input, and not actually my a).

c-cube commented 8 years ago

I'm indeed not sure map_hide is doable, unless I modify the definition of 'a arbitrary to keep a list of intermediate values. For now I'm going to add map' (under the name map_keep_input?), and you can ignore the first value when it comes to testing.

c-cube commented 8 years ago

partially solved by 13e38a5

c-cube commented 8 years ago

I don't think the map_hide is doable (at least now), but please re-open if you disagree or have an idea.