module QCheck:sig..end
This explains the organization of this module:
'a arbitrary is used to describe how to generate random values,
shrink them (make counter-examples as small as possible), print
them, etc. Auxiliary modules such as QCheck.Gen, QCheck.Print, and QCheck.Shrink
can be used along with QCheck.make to build one's own arbitrary instances.QCheck.Test is used to describe a single test, that is, a property of
type 'a -> bool combined with an 'a arbitrary that is used to generate
the test cases for this property. Optional parameters
allow to specify the random generator state, number of instances to generate
and test, etc.
let test =
QCheck.(Test.make ~count:1000
(list int) (fun l -> List.rev (List.rev l) = l));;
QCheck.Test.check_exn test;;
let test = QCheck.(
Test.make
~count:10_000 ~max_fail:3
(list small_nat)
(fun l -> l = List.sort compare l));;
QCheck.Test.check_exn test;;
QCheck.Gen.fix :type tree = Leaf of int | Node of tree * tree
let leaf x = Leaf x
let node x y = Node (x,y)
let g = QCheck.Gen.(sized @@ fix
(fun self n -> match n with
| 0 -> map leaf nat
| n ->
frequency
[1, map leaf nat;
2, map2 node (self (n/2)) (self (n/2))]
))
Gen.generate ~n:20 g;;
More complex and powerful combinators can be found in Gabriel Scherer's
Generator module. Its documentation can be found
here.
val (==>) : bool -> bool -> boolb1 ==> b2 is the logical implication b1 => b2
ie not b1 || b2 (except that it is strict and will interact
better with QCheck.Test.check_exn and the likes, because they will know
the precondition was not satisfied.).
WARNING: this function should only be used in a property
(see QCheck.Test.make), because it raises a special exception in case of
failure of the first argument, to distinguish between failed test
and failed precondition. Because of OCaml's evaluation order,
both b1 and b2 are always evaluated; if b2 should only be
evaluated when b1 holds, see QCheck.assume.
val assume : bool -> unitassume cond checks the precondition cond, and does nothing
if cond=true. If cond=false, it interrupts the current test.
WARNING This function, like QCheck.(==>), should only be used in
a test. not outside.
Example:
Test.make (list int) (fun l ->
assume (l <> []);
List.hd l :: List.tl l = l)
val assume_fail : unit -> 'aassume_fail () is like assume false, but can take any type
since we know it always fails (like assert false).
This is useful to ignore some branches in if or match.
Example:
Test.make (list int) (function
| [] -> assume_fail ()
| _::_ as l -> List.hd l :: List.tl l = l)
module Gen:sig..end
module Print:sig..end
module Iter:sig..end
module Shrink:sig..end
A value of type 'a arbitrary glues together a random generator,
and optional functions for shrinking, printing, computing the size,
etc. It is the "normal" way of describing how to generate
values of a given type, to be then used in tests (see QCheck.Test)
type 'a arbitrary = {
|
gen : |
|||
|
print : |
(* |
print values
| *) |
|
small : |
(* |
size of example
| *) |
|
shrink : |
(* |
shrink to smaller examples
| *) |
|
collect : |
(* |
map value to tag, and group by tag
| *) |
'a arbitrary is an object with a method for generating random
values of type 'a, and additional methods to compute the size of values,
print them, and possibly shrink them into smaller counterexamples
NOTE the collect field is unstable and might be removed, or
moved into QCheck.Test.
val make : ?print:'a Print.t ->
?small:('a -> int) ->
?shrink:'a Shrink.t ->
?collect:('a -> string) -> 'a Gen.t -> 'a arbitraryval set_print : 'a Print.t -> 'a arbitrary -> 'a arbitrary
val set_small : ('a -> int) -> 'a arbitrary -> 'a arbitrary
val set_shrink : 'a Shrink.t -> 'a arbitrary -> 'a arbitrary
val set_collect : ('a -> string) -> 'a arbitrary -> 'a arbitrary
A test is a universal property of type foo -> bool for some type foo,
with an object of type foo arbitrary used to generate, print, etc. values
of type foo.
See QCheck.Test.make to build a test, and QCheck.Test.check_exn to
run one test simply.
For more serious testing, it is better to create a testsuite
and use QCheck_runner.
module TestResult:sig..end
module Test:sig..end
QCheck.arbitraryval choose : 'a arbitrary list -> 'a arbitraryval unit : unit arbitrary(), obviously.val bool : bool arbitraryval float : float arbitraryval pos_float : float arbitraryval neg_float : float arbitraryval int : int arbitraryval int_bound : int -> int arbitraryint_bound n is uniform between 0 and n includedval int_range : int -> int -> int arbitraryint_range a b is uniform between a and b included. b must be
larger than a.val small_nat : int arbitraryval small_int : int arbitrary
val small_signed_int : int arbitraryval (--) : int -> int -> int arbitraryQCheck.int_rangeval int32 : int32 arbitraryval int64 : int64 arbitraryval pos_int : int arbitraryval small_int_corners : unit -> int arbitrarysmall_int, but each newly created generator starts with
a list of corner cases before falling back on random generation.val neg_int : int arbitrarysmall_int, not of pos_int.val char : char arbitraryval printable_char : char arbitraryval numeral_char : char arbitrary'0'..'9'val string_gen_of_size : int Gen.t -> char Gen.t -> string arbitrary
val string_gen : char Gen.t -> string arbitrarysmall_natval string : string arbitrarysmall_nat
and distribution of characters of charval small_string : string arbitrary
val small_list : 'a arbitrary -> 'a list arbitrary0 -- 10).val string_of_size : int Gen.t -> string arbitrarycharval printable_string : string arbitrarysmall_nat
and distribution of characters of printable_charval printable_string_of_size : int Gen.t -> string arbitraryprintable_charval small_printable_string : string arbitrary
val numeral_string : string arbitrarysmall_nat
and distribution of characters of numeral_charval numeral_string_of_size : int Gen.t -> string arbitrarynumeral_charval list : 'a arbitrary -> 'a list arbitrarysmall_natval list_of_size : int Gen.t -> 'a arbitrary -> 'a list arbitraryval array : 'a arbitrary -> 'a array arbitrarysmall_natval array_of_size : int Gen.t -> 'a arbitrary -> 'a array arbitraryval pair : 'a arbitrary -> 'b arbitrary -> ('a * 'b) arbitraryval triple : 'a arbitrary ->
'b arbitrary -> 'c arbitrary -> ('a * 'b * 'c) arbitraryval quad : 'a arbitrary ->
'b arbitrary ->
'c arbitrary ->
'd arbitrary -> ('a * 'b * 'c * 'd) arbitraryval option : 'a arbitrary -> 'a option arbitraryval fun1 : 'a arbitrary -> 'b arbitrary -> ('a -> 'b) arbitraryval fun2 : 'a arbitrary ->
'b arbitrary ->
'c arbitrary -> ('a -> 'b -> 'c) arbitraryfun1 also apply
here.val oneofl : ?print:'a Print.t ->
?collect:('a -> string) -> 'a list -> 'a arbitraryval oneofa : ?print:'a Print.t ->
?collect:('a -> string) -> 'a array -> 'a arbitraryval oneof : 'a arbitrary list -> 'a arbitraryval always : ?print:'a Print.t -> 'a -> 'a arbitraryval frequency : ?print:'a Print.t ->
?small:('a -> int) ->
?shrink:'a Shrink.t ->
?collect:('a -> string) ->
(int * 'a arbitrary) list -> 'a arbitraryQCheck.oneof but with frequenciesval frequencyl : ?print:'a Print.t ->
?small:('a -> int) -> (int * 'a) list -> 'a arbitraryQCheck.oneofl, but each element is paired with its frequency in
the probability distribution (the higher, the more likely)val frequencya : ?print:'a Print.t ->
?small:('a -> int) -> (int * 'a) array -> 'a arbitraryQCheck.frequencyl, but with an arrayval map : ?rev:('b -> 'a) -> ('a -> 'b) -> 'a arbitrary -> 'b arbitrarymap f a returns a new arbitrary instance that generates values using
a#gen and then transforms them through f.rev : if provided, maps values back to type 'a so that the printer,
shrinker, etc. of a can be used. We assume f is monotonic in
this case (that is, smaller inputs are transformed into smaller outputs).val map_same_type : ('a -> 'a) -> 'a arbitrary -> 'a arbitrarymap when the transformation preserves the type, which
makes shrinker, printer, etc. still relevantval map_keep_input : ?print:'b Print.t ->
?small:('b -> int) ->
('a -> 'b) -> 'a arbitrary -> ('a * 'b) arbitrarymap_keep_input f a generates random values from a, and maps them into
values of type 'b using the function f, but it also keeps the
original value.
For shrinking, it is assumed that f is monotonic and that smaller input
values will map into smaller valuesprint : optional printer for the f's output