Module Osnap

OCaml random snapshot testing

The library takes inspiration from ppx_expect, we add random generators to store random application of functions. A snapshot will be the random applications on a function, the snapshot will be latter use to look for diffs between old and new version of a function.

Example:

let spec_add = Osnap.Spec.(int ^> int ^>> string_of_int)

Example:

let test =
  let spec = Osnap.Spec.(int ^> int ^>> int) in
  Osnap.Test.make ~path:".osnap/add" ~spec (+)

Specifying function specification

Spec takes inspiration from OCaml's property-based testing library Monolith. The idea is that the programmer describes the function specification through the set of generators from QCheck and a printer.

Examples:

let add = (+)
let spec_add = Spec.(int ^> int ^>> string_of_int)
let sum = List.fold_left ( + )
let spec_sum = list int ^>> string_of_int
module Spec : sig ... end

Test creation

module Test : sig ... end

Runner

Runner has tree mode:

Interactive mode provides an interactive runner, displaying differences between old and new snapshots. Promoting new version is proposed at every diff, exit when new diff is not promoted, considered as an error.

Example:

let test =
  let spec = OSnap.Spec.(int ^> int ^>> string_of_int) in
  Osnap.Test.make ~count:1 ~path:".osnap/add" ~spec (+)

(* .osnap/add:

   f 5 6 = 11 *)

(* Then, the function under test is updated *)
let test =
  let spec = OSnap.Spec.(int ^> int ^>> int) in
  Osnap.Test.make ~count:1 ~path:".osnap/add" ~spec (fun _ _ -> 0)

let _ = Runner.(run_tests ~mode:Interactive [test])

(* .osnap/add
   -| f 5 6 = 11;
   +| f 5 6 = 0

   Promote changes ? [Y\n] *)

Promote mode provides an automatic promotion of diffs.

Example:

let test =
  let spec = OSnap.Spec.(int ^> int ^>> int) in
  Osnap.Test.make ~count:1 ~path:".osnap/add" ~spec (+)

(* .osnap/add:

   f 5 6 = 11; *)

(* Then, the function under test is updated *)
let test =
  let spec = OSnap.Spec.(int ^> int ^>> int) in
  Osnap.Test.make ~count:1 ~path:".osnap/add" ~spec (fun _ _ -> 0)

let _ = Runner.(run_tests ~mode:Promote [test])

(* .osnap/add has been promoted
   -| f 5 6 = 11;
   +| f 5 6 = 0
*)

Error mode will raise errors on diffs.

let test =
  let spec = OSnap.Spec.(int ^> int ^>> int) in
  Osnap.Test.make ~count:1 ~path:".osnap/add" ~spec (+)

(* .osnap/add:

   f 5 6 = 11; *)

(* Then, the function under test is updated *)
let test =
  let spec = OSnap.Spec.(int ^> int ^>> int) in
  Osnap.Test.make ~count:1 ~path:".osnap/add" ~spec (fun _ _ -> 0)

let _ = Runner.(run_tests ~mode:Promote [test])

(* .osnap/add has differences, exit
   -| f 5 6 = 11;
   +| f 5 6 = 0
*)
module Runner : sig ... end