Since the Testing section of RWO 2nd is still in WIP status , and it might be not easy to find unit test tutorial for OCaml project using Async lib, I put the example here. Let me know if I was wrong.
So, here’s the hello.ml lib that I want to test:
open! Core
open! Async
let get_req simple = Deferred.return simple
let%expect_test "async resp" =
let%bind res = get_req "a" in
Async.print_string res;
[%expect {|a|}]
What you’ve written there seems pretty normal to me. Maybe you could say more about what you think is ugly about it.
It can certainly be a good idea to separate tests into a different library. Some reasons for this are given here.
I agree that it’s not super easy to find examples of this sort of thing with Async specifically (though I don’t think it’s too much different from non-Async expect tests). One not-very-involved example is for cohttp_async_websocket. async_smtp has a more extensive test suite in case that’s useful.
The big advantage of this style is that the initial expected value can be populated automatically by Dune when it first runs the test. This cuts down on the upfront cost of writing each test case. For instance, see this comparison between let%expect_test and let%unit_test.
If you don’t like the expect test style, it’s perfectly possible to write unit-tests of Async code using something like the Alcotest_lwt example you gave:
open! Core
open! Async
let test_get_req () = get_req "a" >>| Alcotest.(check string) "req a" "a"
let () =
don't_wait_for
(Alcotest_async.run __FILE__
[ ("all", [ Alcotest_async.test_case "get_req" `Quick test_get_req ]) ]);
never_returns (Scheduler.go ())
This is quite boilerplate heavy, and alcotest-async requires some work to improve usability, but there is ongoing work to fix both of those problems.
Additionally, expect tests will catch any changes to anything that you print, whether or not that change involves a property that you would have thought to check on your own. This isn’t a silver bullet: you still have to decide what to print. And it can mean that you have to read a bunch of changes that don’t affect the correctness of your code, which in the worst case means you might be more likely to miss the changes that do matter. But I think you do get some benefit from not having to think as much about what you’d like to capture in the tests.
Along the same lines, if you like expect tests they also work just as well when you aren’t testing Async code.