Is it a good practice to use Process.register
in async tests? I’m doing something like this:
Process.register self(), :test
So that I can send messages to :test
and assert whether a callback runs:
MyCode.run fn ->
send :test, :callback_ran
end
assert_receive :callback_ran
I could also grab a reference to self
from inside the callback, with the downside of adding more code/noise.
So far I’m getting no errors with Process.register
, but I wonder if there are drawbacks?
As soon as you do anything that amounts to using global variables, you should either explicitly specify async: false
on the test module or prepare to have really hard to debug sporadic test failures. I love quick test feedback and therefore parallel test suites, so I’ll go through quite some pains to make sure I never need to do global things - it also happens to make your code more robust (what if you pull in a library that registers :test
as well?).
In your example,
me = self()
MyCode.run fn ->
send me, :callback_ran
end
...
should have the same result, for example.
Thanks, @cdegroot. Actually, I was experimenting and tried changing the async test from grabbing a self
reference within the closure (as you exemplified) to using Process.register
, and was not getting failures as a result of that move. So I thought “is there a chance it works differently than I think it does?”
But, as you said, this is flaky and I should expect failures sooner or later.
I found a nice alternative when dealing with more than one test:
setup do
{:ok, self: self()}
end
test "my thing", %{self: me} do
MyCode.run fn ->
send me, :callback_ran
end
assert_receive :callback_ran
end
This avoids repeating me = self()
all over.
1 Like