The correct ways to test a file from the lib folder

Hi there.

I created the project from the tutorial Quickstart an OCaml app project using Dune

dune init project dummy

and edited the lib/dune and lib/lib.ml files to look like this

(* lib/dune *)
(library
  (name lib))
(* lib/lib.ml *)
let add x y = x + y

let sub x y = x - y

When running the command

dune exec dummy 

it executes the program correctly, and prints

Hello, world!

as expected.

So I edited the bin/main.ml file to look like this

open lib

let () =
  let result = add 2 3 in
  print_endline(string_of_int result);
  let result = sub 3 1 in
  print_endline (string_of_int result)

Again, if you run the command

dune exec dummy 

the program will run perfectly, printing

5
2

Then I edited the test/dune file and added the test/dummy.ml file so that it had the following contents (note that I am not calling any test libraries. For now, I just want to make sure I’m able to use the lib/lib.ml file).

(* test/dune *)
(test
  (name dummy)
    (libraries dummy))
(* test/dummy.ml *)

let result = Dummy.Lib.add 7 0 in
  print_endline (string_of_int result);
  let result = Dummy.Lib.sub 72 1 in
  print_endline (string_of_int result)

When running the command

dune runtest

I see the expected result:

7
71

From the above code, I conclude that the fact that lib/lib.ml is inside the dummy project causes Ocaml to create the Dummy and Lib modules, and therefore I can call Dummy.Lib to access the functions in lib/lib.ml.

I modified the code in test/dummy.ml a bit:

(* test/dummy.ml *)
open Dummy

let result = Lib.add 7 0 in
  print_endline(string_of_int result)
  let result = Lib.sub 72 1 in
  print_endline (string_of_int result)

but this time the command

dune runtest

failed:

File "test/dummy.ml", line 4, characters 25-27:
4 | let result = Lib.add 7 0 in
                             ^^
Failed: Syntax error

Only after I added

;;

at the end of the open Dummy line did the code compile and run successfully:

(* test/dummy.ml *)
open Dummy;;

let result = Lib.add 7 0 in
  print_endline(string_of_int result);
  let result = Lib.sub 72 1 in
  print_endline (string_of_int result)

Note: By adding only one

;

I still got a compilation error:

File "test/dummy.ml", line 2, characters 10-11:
2 | open Dummy;
              ^
Error: Syntax error

I think this is a bug. Or am I doing something wrong that I haven’t seen?

About my environment:

Debian GNU/Linux 12
The OCaml version 5.0.0
Opam 2.1.5

This bug was not expected. What I originally wanted to ask is this:

Why do I have to use open Dummy or open Dummy.Lib and I can’t just use open Lib ?

I was hoping that since the test is in the project itself, I could just have the file test/dune

(* test/dune *)
(test
  (name dummy)
    (libraries lib))

and in the test file (test/dummy), either use open Lib or access the function directly with Lib.add.

Thanks in advance.

See Syntax Error on "in" - #5 by yawaramin

1 Like

The single ; is used to separate expressions (like print_int 5). open Module is not an expression but a statement.

1 Like

As a followup to the other good advice you’ve received, correcting your syntax error should sort you out:

open Dummy

let () =
  let result = Lib.add 7 0 in
  print_endline(string_of_int result);
  let result = Lib.sub 72 1 in
  print_endline (string_of_int result)
1 Like

It worked like a charm.

But I don’t understand why do I need to use let () =.

I was poking around the docs and samples and it seemed to me that there is not a main function to work as an entry point in Ocaml (like the main() in C, for instance).

I’m also aware that let () = is used as an entry point.

When I had the code

(* test/dummy.ml *)

let result = Dummy.Lib.add 7 0 in
  print_endline (string_of_int result);
  let result = Dummy.Lib.sub 72 1 in
  print_endline (string_of_int result)

It worked without the let () =.

Thank you.

Also, why do I need

It probably just happened to work because you only had one expression in the entire file. Always use the let () = ... at the top level of a module for each expression that is not defining an identifier for later use, but is only for side effects – just like main in other languages.

2 Likes

Ah, I see… Thank you.