Generation of Base_quickcheck generators, observers, and shrinkers from types.
Type definitions: [@@deriving quickcheck]
Expressions: [%quickcheck.generator: TYPE], [%quickcheck.observer: TYPE],
and [%quickcheck.shrinker: TYPE].
We use ppx_deriving/ppx_type_conv, so type definitions are annotated this way:
type a = b * c [@@deriving quickcheck]This generates definitions for quickcheck_generator_a, quickcheck_observer_a, and
quickcheck_shrinker_a. The generator definition is based on quickcheck_generator_b and
quickcheck_generator_c; likewise for the observer and shrinker.
Following Jane Street's naming conventions, we assume that a type named t is the main
type in a module, and we omit the _t suffix for its generated definitions.
type t = A.t * B.t [@@deriving quickcheck]This generates definitions for quickcheck_generator, quickcheck_observer, and
quickcheck_shrinker. The definitions are based on A.quickcheck_generator,
B.quickcheck_generator, and so on.
type t [@@deriving quickcheck] in a module signature adds
val quickcheck_generator : t Base_quickcheck.Generator.t,
val quickcheck_observer : t Base_quickcheck.Observer.t, and
val quickcheck_shrinker : t Base_quickcheck.Shrinker.t to the module type.
Sometimes you just want to run Quickcheck without having to create a new type. You can
create generators, observers, and shrinkers using [%quickcheck.generator: ...],
[%quickcheck.observer: ...], and [%quickcheck.shrinker: ...]:
let generator = [%quickcheck.generator: float * int * [`A | `B | `C]]
let observer = [%quickcheck.observer: float * int * [`A | `B | `C]]
let shrinker = [%quickcheck.shrinker: float * int * [`A | `B | `C]]For maps, the syntax that works is [%quickcheck.generator: bool Map.M(String).t].
The @quickcheck.generator attribute overrides the distribution for a type.
type ranking =
{ name : (string [@quickcheck.generator Generator.string_of Generator.char_alpha])
; high_score : (int [@quickcheck.generator Generator.int_inclusive 0 999_999])
}
[@@deriving quickcheck]The @quickcheck.weight attribute overrides the weight with which a variant clause is
chosen. The default weight for each clause is 1.
type tree =
| Leaf
| Node1 of tree * int * tree [@quickcheck.weight 1. /. 2.]
| Node2 of tree * int * tree * int * tree [@quickcheck.weight 1. /. 3.]
[@@deriving quickcheck]The @quickcheck.do_not_generate attribute leaves a variant out of
the generator entirely. This is similar to [@quickcheck.weight 0.],
but it does not require generators for the variant arguments to exist.
Observers and shrinkers are not altered by this attribute.
type v =
| A
| B of Something_that_cannot_be_generated.t [@quickcheck.do_not_generate]
[@@deriving quickcheck]The expression extensions allow custom generators, observers, and shrinkers beyond just
the default for a given type. In place of any type, use [%custom ...] to fill in an
arbitrary expression.
let generator = [%quickcheck.generator: [%custom Generator.int_uniform] * char * string]
let observer = [%quickcheck.observer: int * [%custom Observer.opaque] * string]
let shrinker = [%quickcheck.shrinker: int * char * [%custom Shrinker.atomic]]Use the ~unboxed attribute to also derive for implicit unboxed records:
(* This: *)
type t = { x : Int64_u.t; y : Int64_u.t } [@@deriving quickcheck ~unboxed]
(* will derive this: *)
val quickcheck_generator : t Base_quickcheck.Generator.t
val quickcheck_generator_u : t# Base_quickcheck.Generator.t
val quickcheck_observer : t Base_quickcheck.Observer.t
val quickcheck_observer_u : t# Base_quickcheck.Observer.t
val quickcheck_shrinker : t Base_quickcheck.Shrinker.t
val quickcheck_shrinker_u : t# Base_quickcheck.Shrinker.tFor types other than t, the type name appears before _u:
(* This: *)
type s = { x : Int64_u.t; y : Int64_u.t } [@@deriving quickcheck ~unboxed]
(* will derive this: *)
val quickcheck_generator_s : s Base_quickcheck.Generator.t
val quickcheck_generator_s_u : s# Base_quickcheck.Generator.t
val quickcheck_observer_s : s Base_quickcheck.Observer.t
val quickcheck_observer_s_u : s# Base_quickcheck.Observer.t
val quickcheck_shrinker_s : s Base_quickcheck.Shrinker.t
val quickcheck_shrinker_s_u : s# Base_quickcheck.Shrinker.t