How to test requests and websockets? [depends on Dream client]
Is there any recommended way or documentation on how to tests controllers and websockets?
I could use external tools, for example connect to the server with javascript and initiate websockets there, but it would be nice if we could do this from ocaml directly and use dune to run the tests
There is some (not much) support for in-process no-network testing, see section Testing. In particular, Dream.request can be used to artificially create a request, and then Dream.test runs it through a web app. Dream's own unit test suite (highly incomplete; I've been relying on the examples so far) uses this. For example, see this helper used to define most of the router tests:
https://github.com/aantron/dream/blob/500f4d0d37e5b0dcc4d4283ef5a36f2226c6caea/test/expect/middleware/router.ml#L83-L99
These are expect tests, so they just print to STDOUT/STDERR, and ppx_expect compares them with correct output.
There is nothing else besides that, but I do have a notes item to look into this. I'd appreciate it very much if you would let me know what type of testing you'd like to do, and/or provide me with a link to some implementation of it (in JS or elsewhere). I'd then see how it should be supported in Dream or at least in OCaml.
There is nothing for testing WebSockets conveniently at the moment, a definite gap. To test them immediately, you'd need to do end-to-end tests with an external tool.
There is nothing for testing WebSockets conveniently at the moment, a definite gap. To test them immediately, you'd need to do end-to-end tests with an external tool.
That's what I was thinking about and what I was afraid of... Basically what I would want is to be able to start a Dream.websocket in a test and be able to connect clients to it.
I know how to do it with external tools, but it's a bit of overhead and not as fun as being able to do directly.
For other tests, I like the phoenix tests (https://hexdocs.pm/phoenix/testing_controllers.html) For example:
describe "index" do
test "lists all posts", %{conn: conn} do
conn = get(conn, Routes.post_path(conn, :index))
assert html_response(conn, 200) =~ "Listing Posts"
end
end
(I don't think =~ is something ppx_expect can do)
They also have nice tests for websockets:
setup do
{:ok, _, socket} =
UserSocket
|> socket("user_id", %{some: :assign})
|> subscribe_and_join(RoomChannel, "room:lobby")
%{socket: socket}
end
test "ping replies with status ok", %{socket: socket} do
ref = push(socket, "ping", %{"hello" => "there"})
assert_reply ref, :ok, %{"hello" => "there"}
end
Of course this is not for a general websocket connection, but you get the point.
Another example:
If I want to write a unit test around something that manages the current clients connected to websockets (Dream.websocket), I see no way of creating these Dream.websockets in a test contest.
I started creating Hyper last year, the client counterpart to Dream. It likely can address parts of this issue.
In particular, the client's requesting functions are request -> response promise functions, and a Dream Web app has the same type signature (before it is passed to Dream.run/Dream.serve). One of Hyper's test suites, nohttp, implements the server by directly calling the server function. Of course, there are tests with actual HTTP transports as well.
I expect this would eventually be useful for the users' Dream (and Hyper) testing.