Tutorial for setting up test suite with Alcotest + Dune?

I want to write some tests for my first OCaml project…

Alcotest seems popular(?), I am open to using Ounit or another library instead. I don’t want to do inline tests for now.

I’ve seen Dune provides a dune runtest command which I’d like to use: Writing and running tests — dune documentation

…however I’m having trouble relating the high-level overview in the docs to a concrete scenario.

I have a directory structure like:

lib/
  dune
  mymodule.ml
tests/
  mymodule.ml

I think I need a dune file in tests/ too… I am unclear what it should contain though.

The docs for dune and alcotest show things like dune exec tests/mytests.exe so I guess it needs to define an executable. I have added one that looks like:

(executable
  (name mymodule)
  (modules mymodule)
  (libraries alcotest))

it seems like I should have a (tests (names ???)) stanza in there too, but I can’t find a combination of incantations that works.

I would also like to be able to have multiple files under tests/ and be able to run them all or individually.

Can anyone recommend a complete end-to-end tutorial for setting up tests and running them with Dune?

2 Likes

Hi @anentropic,

I think you’re close to having a full set-up already, so I’ll try to respond to your questions directly:

  • the dune test / tests stanzas are all that’s necessary for setting up test binaries. It’s not necessary to explicitly define these as executables – Dune does this for you. The difference is that binaries specified as tests are attached to the @runtest alias: this means that they’re hooked into dune runtest / dune test.

  • define one test for each test binary you want (or a single tests stanza if you have multiple of them in the same folder). Then you can do:

    • dune test, to run all test binaries.
    • dune build @path/to/test/dir/runtest, to run all test binaries under “path/to/test/dir”.
    • dune exec path/to/test/foo.exe to run the test with name “foo” in the folder “path/to/test”.

Alcotest’s documentation is lacking w.r.t. explaining how to plumb the library into Dune. I’ll try to add something constructive soon.

1 Like

Update…

with:

tests/
  dune
  one.ml
  two.ml

I put this in my tests/dune file:

(tests
  (names one two)
  (libraries
    alcotest
    mylib))

dune runtest then ran the alcotest tests from both one and two … great!

But dune runtest one gives:
Error: Don’t know about directory one specified on the command line!

Thank you @CraigFe for your reply, after reading that I see I can do:
dune exec tests/one.exe to run just one file

However after doing that, when I go back and do dune runtest nothing happens :thinking:

Have you tried dune runtest --force? Dune will cache test outputs if it thinks nothing has changed. My go-to command is something like:

; dune runtest --force --watch --terminal-persistence=clear-on-rebuild

which re-runs the tests automatically while I’m working on the code.

(Perhaps worth adding that none of the above is specific to Alcotest: the process would be the same when using Ounit or any other unit-testing library, with the exception of those that work via inline_tests or PPX. This is probably why the Alcotest docs don’t explain this properly – although that’s not a good excuse :stuck_out_tongue: )

Thanks, that works :slight_smile:

1 Like

Yeah, it’s maybe more on the Dune side it could use a more comprehensive example.

There is one snippet there like:

(tests (names test1 test2))

…but it’s not clear at all what that means, that it’s a top-level stanza, or how it fits with the other stanzas discussed and how it relates back to the files in the dir.