Unit testing with OCaml

Stefan Alfbo - Sep 17 '23 - - Dev Community

One of the first steps when I'm starting to learn a new programming language is to figure out how to do unit testing in that language. We are all wired differently, but unit testing is a perfect tool to experiment/testing syntax, features, scopes, and about everything in a programming language.

I recently picked up and started to play with OCaml and it has an awsome REPL (called toplevel) tool which is a great substitute for unit tests to learn and testing the OCaml language for those that prefer that instead.

However lets try to set up a simple project with some unit tests with Ounit2. This assumes that OCaml with the build system Dune is installed.



# Create project
dune init proj unit_test_example
cd unit_test_example

# Install the OUnti2 testing framework
opam install ounit2

# Open the IDE
code .


Enter fullscreen mode Exit fullscreen mode

Navigate to the file, main.ml, should be located in the bin directory.

Explorer
Replace the current code in main.ml with this.



let () =
  match Sys.argv with
  | [| _; n |] -> Unit_test_example.Factorial.factorial (int_of_string n) |> print_int; print_newline ()
  | _ -> 
    print_endline "Usage: unit_test_example [n]";
    exit 64


Enter fullscreen mode Exit fullscreen mode

The code above wants to use a function, factorial, that is defined in a module called Factorial. Jump to the lib directory and create the file, factorial.ml, there to start to solve that issue.

factorial.ml

In that file we will create the code that we want to test.



let rec factorial n =
  match n with 
  | 0 | 1 -> 1
  | _ -> n * factorial (n - 1)


Enter fullscreen mode Exit fullscreen mode

Now it's time to create our tests for the factorial code. Open the file, unit_test_example.ml in the test directory and paste following code into that file.



open OUnit2

let test_factorial_of_zero _ =
  assert_equal 1 (Unit_test_example.Factorial.factorial 0)

let test_factorial_of_five _ =
  assert_equal 120 (Unit_test_example.Factorial.factorial 5)


let () =
  run_test_tt_main
    ("factorial tests" >:::
       [
         "factorial of zero" >:: test_factorial_of_zero;
          "factorial of five" >:: test_factorial_of_five;
       ])


Enter fullscreen mode Exit fullscreen mode

Here we create two simple tests that asserts the expected value for factorial zero and five. The entry function, let (), is then calling our test functions. Before we are able to run our unit tests we will need to configure our dune file to recognize the lib file, factorial.ml, first. Do this by open the file dune that is located in the test directory.

dune file for test

This file should look like this.



(test
 (name unit_test_example)
 (libraries ounit2 unit_test_example))


Enter fullscreen mode Exit fullscreen mode

The third line is added to configure that the test library is aware of the Ounit2 library and our unit_test_example library.

We are now ready to run our unit tests.

dune test

Now we have something to tinker with to explore the OCaml land.

And if you would like to run the program from the CLI you can execute it like this.



# Where 5 is the factorial to calculate
dune exec ./bin/main.exe -- 5


Enter fullscreen mode Exit fullscreen mode

Happy testing!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .