Testing, Documentation & Debugging

Run dune test; if output differs, dune promote updates the expectation.

24.1 Alcotest (unit tests)

let test_add () = Alcotest.(check int) "same ints" 4 (2 + 2)
let test_rev () = Alcotest.(check (list int)) "rev" [3;2;1] (List.rev [1;2;3])

let () =
  Alcotest.run "MyLib" [
    "arith", [ Alcotest.test_case "add" `Quick test_add ];
    "list",  [ Alcotest.test_case "rev" `Quick test_rev ];
  ]

24.2 Expect tests (ppx_expect)

Run dune test; if output differs, dune promote updates the expectation.

(library (name mylib) (inline_tests) (preprocess (pps ppx_expect)))
let%expect_test "addition" =
  print_int (1 + 2);
  [%expect {| 3 |}]

24.3 Inline tests

let%test "rev" = List.rev [1;2] = [2;1]
let%test_unit "sorted" = assert (List.sort compare [2;1] = [1;2])

24.4 Property-based testing (QCheck)

let rev_involutive =
  QCheck.Test.make ~count:1000 ~name:"rev twice"
    QCheck.(list int) (fun l -> List.rev (List.rev l) = l)

let () = QCheck_runner.run_tests_main [ rev_involutive ]

24.5 Cram tests (CLI testing)

$ myapp --version
  1.0.0

24.6 Documentation with odoc

dune build @doc → _build/default/_doc/_html/index.html.

(** [clamp ~lo ~hi x] returns [x] bounded to [\[lo, hi\]].

    {[
      clamp ~lo:0 ~hi:10 15 = 10
    ]}
    @raise Invalid_argument if [lo > hi]. *)
val clamp : lo:int -> hi:int -> int -> int

24.7 Debugging techniques

Print debugging: Printf.eprintf, Format.eprintf "%a".

#trace in the toplevel: #trace fib;; fib 3;; Backtraces: OCAMLRUNPARAM=b./prog

ocamldebug (bytecode, supports time-travel): ocamlc -g, ocamldebug ./prog.

gdb/lldb on native code (OCaml 5 emits DWARF CFI).

Landmarks / perf / memtrace for profiling (see §40).

ppx_deriving.show to auto-generate printers for debugging.

🧪 Part II Exercises

Implement a binary search tree module with signature BST (insert, mem, remove, to_list, height).

Write a functor MakeCache (K : Hashtbl.HashedType) producing a memoising cache.

Build a bank account module with an abstract type where the balance can't go negative (return result).

Write a word-frequency counter reading a file, using Hashtbl, and printing the top 10 words.

Implement a priority queue (leftist heap) as a functor over ORDERED.

Write a CSV parser that handles quoted fields, returning (string list list, string) result.

Implement a stack-based RPN calculator using variants and exceptions.

Create a dune project with a library, an executable, and alcotest tests.

Convert an imperative bubble sort on arrays into a functional insertion sort on lists.

Write an interpreter for the expr type in §12.4 with error handling via result.