Skip to main content


In the Test module, we provide very basic assertion material.

The framework doesn't handle comparisons for you, you'll need to provide your comparator functions. The goal is to avoid expensive recursive comparisons as much as possible (while still letting you do them if necessary).


Assertion is the basic building block, here's its signature:

assertion(  // comparison function, returns a boolean  comparator,  // the value you're testing  a,  // the value you're expecting  b,  // optional, gives a name in case of test failure  ~operator: string=?,  // optional, gives a message on the test line  ~message: string=?,)

Let's write a simple assertion:

assertion(  (a, b) => a === b,  1,  1,  ~operator="Int equals",  ~message="One equals one",)

You can see how this can be a bit redundant. What we recommend is to create an Assert.res file containing the most common assertions:

let intEqual = (~message=?, a: int, b: int) =>  assertion(~message?, ~operator="Int equals", (a, b) => a === b, a, b)

And reuse them across your tests:

open Testopen Assert
test("Add", () => {  intEquals(add(1, 1), 2)  intEquals(~message="1 + 2 === 3", add(1, 2), 3)})


test("Test with a function that's supposed to throw", () => {  throws(() => {    myFunction()  })
  throws(() => {    myFunction()  }, ~message="myFunction throws")
  throws(    () => myFunction(),    ~message="myFunction throws",    ~test=exn => {      // test than exn is the one expected    },  )})

Any exception thrown outside of a throws call will result in the runner exiting with code 1


test("Test with a function that's not supposed to throw", () => {  doesNotThrow(() => {    myFunction()  })
  doesNotThrow(() => {    myFunction()  }, ~message="myFunction doesn't throw")})


When you simply need to validate than a certain code path is reached, asserting a pass is enough:

test("Test with pass", () => {  myFunction(() => {    pass()  })  myFunction(() => {    pass(~message="Callback is reached", ())  })})


The other way around, when you want to assert that you don't reach a certain path:

test("Test with fail", () => {  myFunction(() => {    fail()  })  myFunction(() => {    fail(~message="Callback is not reached", ())  })})


If you're in a hurry and want to remember you'll eventually need to write this test:

test("Test with todo", () => {  todo("Check that int overflows are handled")})