package qcheck

  1. Overview
  2. Docs

Quickcheck inspired property-based testing

The library takes inspiration from Haskell's QuickCheck library. The rough idea is that the programer describes invariants that values of a certain type need to satisfy ("properties"), as functions from this type to bool. She also needs to desribe how to generate random values of the type, so that the property is tried and checked on a number of random instances.

This explains the organization of this module:

  • Arbitrary is used to describe how to generate random values. An 'a Arbitrary.t is a random generator of values of type 'a.
  • Prop is used to describe and combine properties. Especially interesting is Prop.(==>), that is such that a ==> b only checks the property b on a value x if a x holds (precondition).
  • PP describes a few combinators to print values. This is used when a property fails on some instances, to print the failing instances.

Then, a few functions are provided to test properties. Optional parameters allow to specify the random generator, the printer for failing cases, the number of instances to generate and test...

Examples:

  • List.rev is involutive:
let test = QCheck.mk_test ~n:1000 QCheck.Arbitrary.(list alpha)
  (fun l -> List.rev (List.rev l) = l);;
QCheck.run test;;
  • Not all lists are sorted (false property that will fail. The 15 smallest counter-example lists will be printed):
let test = QCheck.(
  mk_test
    ~n:10_000 ~size:List.length ~limit:15 ~pp:QCheck.PP.(list int)
    QCheck.Arbitrary.(list small_int)
    (fun l -> l = List.sort compare l));;
QCheck.run test;;
type tree = Int of int | Node of tree list;;

let ar = QCheck.Arbitrary.(fix ~max:10
 ~base:(map small_int (fun i -> Int i))
 (fun t st -> Node (list t st)));;

Arbitrary.generate ~n:20 ar;;

More complex and powerful combinators can be found in Gabriel Scherer's Generator module. Its documentation can be found here.

Description of how to generate arbitrary values for some type

module Arbitrary : sig ... end

Pretty printing

module PP : sig ... end

Testing

QCheck helps you test invariants, or properties. This submodule helps dealing with such properties. A property of the 'a type is a predicate 'a -> bool.

If the property doesn't have to hold for all values of type 'a, you can use Prop.assume or Prop.assume_lazy in the body of the property. Doing so will "filter" irrelevant values (the one which do not satisfy the assumption) out (in practice it raises an exception).

module Prop : sig ... end
type 'a result =
  1. | Ok of int * int
    (*

    total number of tests / number of failed preconditions

    *)
  2. | Failed of 'a list
    (*

    Failed instances

    *)
  3. | Error of 'a option * exn
    (*

    Error, and possibly instance that triggered it

    *)
val check : ?call:('a -> bool -> unit) -> ?rand:Random.State.t -> ?n:int -> 'a Arbitrary.t -> 'a Prop.t -> 'a result

Check that the property prop holds on n random instances of the type 'a, as generated by the arbitrary instance gen

  • parameter call

    function called on each test case, with the result

Main

type test

A single property test

val name : test -> string option
val mk_test : ?n:int -> ?pp:'a PP.t -> ?name:string -> ?size:('a -> int) -> ?limit:int -> 'a Arbitrary.t -> 'a Prop.t -> test

Construct a test. Optional parameters are the same as for run.

  • parameter name

    is the name of the property that is checked

  • parameter pp

    is a pretty printer for failing instances @out is the channel to print results onto @n is the number of tests (default 100) @rand is the random generator to use @size is a size function on values on which tests are performed. If the test fails and a size function is given, the smallest counter-examples with respect to size will be printed in priority. @limit maximal number of counter-examples that will get printed. Default is 10.

val run : ?verbose:bool -> ?out:out_channel -> ?rand:Random.State.t -> test -> bool

Run a test and print results

type suite = test list

A test suite is a list of tests

val flatten : suite list -> suite
val run_tests : ?verbose:bool -> ?out:out_channel -> ?rand:Random.State.t -> suite -> bool

Run a suite of tests, and print its results

  • parameter verbose

    if true, prints more information about test cases (@since 0.4)

val run_main : ?argv:string array -> suite -> unit

Can be used as the main function of a test file. Exits with a non-0 code if the tests fail.

  • since 0.4
OCaml

Innovation. Community. Security.