Module QCheck2.Shrink

Shrinking helper functions.

Shrinking is used to reduce the size of a counter-example. It tries to make the counter-example smaller by decreasing it, or removing elements, until the property to test holds again; then it returns the smallest value that still made the test fail.

This is meant to help developers find a simpler counter-example to ease investigation and find more easily the root cause (be it in the tested code or in the test).

This module exposes helper functions that one can reuse in combination with Gen.make_primitive to craft custom primitive generators (not by composing other generators). The vast majority of use cases will probably not need this module.

module type Number = sig ... end

Util module representing a number type, used for ad hoc polymorphism of some functions like number_towards.

val number_towards : (module Number with type t = 'a) -> destination:'a -> 'a -> 'a Stdlib.Seq.t

Shrink a number by edging towards a destination.

The destination is always the first value for optimal shrinking.

let int64_towards_list destination x = List.of_seq @@
  Gen.number_towards (module Int64) ~destination x
in
assert (int64_towards_list 0L 100L =
        [0L; 50L; 75L; 88L; 94L; 97L; 99L]);
assert (int64_towards_list 500L 1000L =
        [500L; 750L; 875L; 938L; 969L; 985L; 993L; 997L; 999L]);
assert (int64_towards_list (-50L) (-26L) =
        [-50L; -38L; -32L; -29L; -28L; -27L])

This generic function is exposed to let users reuse this shrinking technique for their custom number types. More specialized, convenient functions are provided below, e.g. int_towards.

val int_towards : int -> int -> int Stdlib.Seq.t

number_towards specialized to int.

val int32_towards : int32 -> int32 -> int32 Stdlib.Seq.t

number_towards specialized to int32.

val int64_towards : int64 -> int64 -> int64 Stdlib.Seq.t

number_towards specialized to int64.

val float_towards : float -> float -> float Stdlib.Seq.t

number_towards specialized to float.

There are various ways to shrink a float:

  • try removing floating digits, i.e. towards integer values
  • try to get as close as possible to the destination, no matter the number of digits
  • a mix of both

This implementation, as it relies on the generic number_towards function, tries to get as close as possible to the destination, e.g. the last value of Gen.float_towards 50 100 may be 99.9969482421875 (or a similar value).

val int_aggressive_towards : int -> int -> int Stdlib.Seq.t

int_agressive_towards destination n gives all integers from destination to n (excluded).

Be careful about time and memory as the resulting list can be huge

val int_aggressive : int -> int Stdlib.Seq.t
  • deprecated

    Use int_aggressive_towards 0 instead.

  • since 0.7