Module B0_testing.Test

Testing structure and assertions.

See an example.

Source locations

type loc = string * int * int * int

The type for test source locations. This is the type of Stdlib.__POS_OF__.

It is an optional argument of most combinators to keep track of precise locations of failures. The idea is that the argument is simply used with Stdlib.__POS__. For example:

Test.string s0 s1 ~__POS__

Logging

type 'a log = ?__POS__:loc -> ('a, Stdlib.Format.formatter, unit, unit) Stdlib.format4 -> 'a

The type for log functions. If __POS__ is specified starts by logging the position on a line before logging the format.

val log : 'a log

log fmt … logs a message formatted by fmt.

val log_pass : 'a log

log_pass fmt … is like log but formatted for passing. This does not increment passed assertions, use pass to do so.

val log_fail : 'a log

log_fail fmt … is like log but formatted for failures. This does not increment failed assertions, use fail to register a failure.

val log_start : 'a log

log_start is like log but does not finish the line. log_end does.

val log_finish : ('a, Stdlib.Format.formatter, unit, unit) Stdlib.format4 -> 'a

log_finish ends a line started with log_start.

val log_raw : ('a, Stdlib.Format.formatter, unit, unit) Stdlib.format4 -> 'a

log_raw fmt … outputs to the test log.

Main & tests

val main : ?doc:string -> ?name:string -> (unit -> unit) -> int

main f executes f (), logs the resulting testing status and returns 0 if all tests passed and 1 otherwise to be given to Stdlib.exit. Usually f calls functions that call test.

  • doc is a synopsis for the test executable.
  • name is a name for the test executable.

See an example.

val main' : ?man:Cmdliner.Manpage.block list -> ?doc:string -> ?name:string -> 'a Cmdliner.Term.t -> ('a -> unit) -> int

main' is like main but allows to define your own additional command line.

val set_main_exit : (unit -> int) -> unit

set_main_exit f will disable the final report performed by main and invoke f instead. TODO. A bit ad-hoc.

module Arg : sig ... end

Test arguments.

val test : ?long:bool -> string -> (unit -> unit) -> unit -> unit

test name f is a test that when run logs "Test %s" name and executes f (). The test fails if any failure is reported in f or if f raises an unexpected exception. If long is true, this is a long test an only run when explicitely requested. See examples.

val test' : 'a Arg.t -> ?long:bool -> string -> ('a -> unit) -> 'a -> unit

test' arg is like test but takes an argument.

val autorun : ?args:Arg.value list -> unit -> unit

autorun () calls all the tests defined by test and test', possibly filtered by the command line. For the latter an argument value should be provided in args (defaults to []).

Stop, pass, skip and fail

A test is usually made of many assertions. If an assertion fails the test fails.

val stop : unit -> 'a

stop () stops the current block, test, or main. Note that this does not increment failed assertions, use fail or failstop for that.

val skip : 'a log

skip () skips the current block, test, or main.

val pass : unit -> unit

pass () increments the number of successfull assertions.

val fail : 'a log

fail fmt … increments the number of failed assertions and logs fmt with log_fail. The test or block continues to execute, use stop or failstop to stop the test.

val failstop : ?__POS__:loc -> ('a, Stdlib.Format.formatter, unit, 'b) Stdlib.format4 -> 'a

failf fmt … is like fail but also stops the test.

Blocks and loops

Blocks and loops can be used as larger sub units of test which you can stop and failstop without stopping the test itself.

val block : ?fail:(?__POS__:loc -> int -> assertions:int -> unit) -> ?__POS__:loc -> (unit -> unit) -> unit

block ~fail f runs f (), if that results in n > 0 failed assertions, fail n ~assertions is called afterwards with assertoins the total number of assertions that were performed. If f peforms a failstop the block is stopped but not the test. It is possible to fail stop the test by stoppping in fail.

TODO. Should we simply make blocks nested tests ?

val range : ?kind:string -> first:int -> last:int -> ?__POS__:loc -> (int -> unit) -> unit

range ~first ~last f calls f n with n ranging over the range [first;last]. If a failure occurs for n, logs "%s in range [%d;%d] failed on %d" kind first last n. If f performs a failstop the loop is stopped but not the test. kind defaults to "Test".

Testers

module type T = sig ... end

The type for testable values.

module T : sig ... end

Testers.

module Diff : sig ... end

Reporting value differences.

module Patch : sig ... end

Patching text and files.

Assertions

type 'a eq = ?diff:'a Diff.t -> ?__POS__:loc -> 'a -> 'a -> unit

The type for functions aasserting equality. diff indicates how to report differences on mismatches.

val eq : 'a T.t -> 'a eq

eq t fnd exp assert fnd and exp are equal using tester t.

Convention. When testing values we assume that the second value is the expected argument and the first one the value against which it is checked.

val neq : 'a T.t -> 'a eq

neq t fnd exp assert fnd and exp are not equal using tester t.

val holds : ?msg:string -> ?__POS__:loc -> bool -> unit

holds b asserts that b is true. msg is logged if the assertion fails.

Exceptions

val noraise : ?__POS__:loc -> (unit -> 'a) -> 'a

noraise f tests that f () does not raise an exception and fail stops if it does except if this is a B0_std.Os.exn_don't_catch exception.

val catch : ?ret:'a T.t -> ?__POS__:loc -> (unit -> 'a) -> (exn -> unit) -> unit

catch f k calls f () and gives the exception it raises to k or fails otherwise. ret is used to print an offending returned value. B0_std.Os.exn_don't_catch exceptions are not catched.

val exn : exn eq

ex is eq Exceptions.

val raises : ?ret:'a T.t -> ?exn:exn T.t -> ?diff:exn Diff.t -> ?__POS__:loc -> exn -> (unit -> 'a) -> unit

raises exn f tests that f () raises exception exn. B0_std.Os.exn_don't_catch exceptions are not catched.

val invalid_arg : ?ret:'a T.t -> ?diff:exn Diff.t -> ?__POS__:loc -> (unit -> 'a) -> unit

invalid_arg f tests that f () raises Invalid_argument _. Note. It is usually better to use Snap.raise as it allows to keep track of the error message.

val failure : ?ret:'a T.t -> ?diff:exn Diff.t -> ?__POS__:loc -> (unit -> 'a) -> unit

failure f tests that f () raises Failure _. Note. It is usually better to use Snap.raise as it allows to keep track of the error message.

Base types

val unit : unit eq

unit is eq T.unit.

val bool : bool eq

bool is eq T.bool.

val int : int eq

int is eq T.int.

val int32 : int32 eq

int32 is eq T.int32.

val uint32 : int32 eq

uint32 is eq T.uint32.

val int64 : int64 eq

int64 is eq T.int64.

val uint64 : int64 eq

uint64 is eq T.uint64.

val nativeint : nativeint eq

nativeint is eq T.nativeint.

val nativeuint : nativeint eq

nativeuint is eq T.nativeuint.

val float : float eq

float is eq T.float.

Character and strings

val char : char eq

char is eq T.char.

val string : string eq

string is eq T.string. Assumes UTF-8 encoded strings.

val lines : string eq

lines is eq T.lines. Assumes UTF-8 encoded strings.

val binary_string : string eq

binary_string is eq T.binary_string. Assumes arbitrary binary strings.

val styled_string : string eq

styled_string is eq T.styled_string. Assumes strings with ANSI escape sequences.

val bytes : bytes eq

string is eq T.bytes.

Parametric types

val any : 'a eq

any uses T.any.

val option : 'a T.t -> 'a option eq

option some is eq (T.option some).

val either : left:'a T.t -> right:'b T.t -> ('a, 'b) Either.t eq

either ~left ~right is eq (T.either ~left ~right).

val result : ok:'a T.t -> ('a, string) Stdlib.result eq

result ~ok is eq (T.result ~ok).

val result' : ok:'a T.t -> error:'e T.t -> ('a, 'e) Stdlib.result eq

result' ~ok ~error is eq (T.result' ~ok ~error).

val list : 'a T.t -> 'a list eq

list elt is eq (T.list elt).

val array : 'a T.t -> 'a array eq

array elt is eq (T.array elt).

val pair : 'a T.t -> 'b T.t -> ('a * 'b) eq

pair fst snd is eq (T.pair fst snd).

val t2 : 'a T.t -> 'b T.t -> ('a * 'b) eq

t2 is pair.

val t3 : 'a T.t -> 'b T.t -> 'c T.t -> ('a * 'b * 'c) eq

t3 is eq for triplets.

val t4 : 'a T.t -> 'b T.t -> 'c T.t -> 'd T.t -> ('a * 'b * 'c * 'd) eq

t4 is eq for quadruplets.

val t5 : 'a T.t -> 'b T.t -> 'c T.t -> 'd T.t -> 'e T.t -> ('a * 'b * 'c * 'd * 'e) eq

t5 is eq for quintuplets.

val t6 : 'a T.t -> 'b T.t -> 'c T.t -> 'd T.t -> 'e T.t -> 'f T.t -> ('a * 'b * 'c * 'd * 'e * 'f) eq

t6 is eq for sextuplets.

Randomized testing

module Rand : sig ... end

Randomized testing.

Snapshot testing

module Snapshot : sig ... end

Snapshot tests.

type 'a snap = ?diff:'a Diff.t -> 'a -> 'a Snapshot.t -> unit

The type for snapshot functions.

val snap : ?subst:'a Snapshot.subst -> 'a T.t -> 'a snap

snap t fnd @@ __POS_OF__ exp compares snapshot fnd to exp. subst is used to correct snapshots, it defaults to Snapshot.generic_subst which depends on t's pretty printer formatting valid OCaml code.

See B0_testing.Snap for preapplied combinators.

Low-level modules

These modules are not needed for basic B0_testing usage.

Command line arguments

module Cli : sig ... end

Command line.

Formatters

module Fmt : sig ... end

Formatters for test runners and tested values.