Assert one process gets message from another
Erlang has a very useful-for-testing function :erlang.trace/3, that can serve as a window into all sorts of behaviour.
In this case I want to test that one process sent a message to another. While it's always best to test outputs rather than implementation, when everything is asynchronous and paralleized you might need some extra techniques to verify your code works right.
pid_a =
spawn(fn ->
receive do
:red -> IO.puts("got red")
:blue -> IO.puts("got blue")
end
end)
:erlang.trace(pid_a, true, [:receive])
spawn(fn ->
send(pid_a, :blue)
end)
assert_receive({:trace, captured_pid, :receive, captured_message})
assert captured_pid == pid_a
assert :blue == captured_message
In the above example we setup a trace on receive
for the first process:
:erlang.trace(pid_a, true, [:receive])
Now, the process that called trace
will receive a message whenever traced process receives a message. That message will look like this:
{
:trace,
pid_that_received_the_message,
:receive, # the action being traced
message_that_was_received
}
This in combination with assert_receive
allows you to test that the test process receives the trace message.