leorodriguesrj
Is it possible to have elixir running with a custom node name during tests?
In Erlang, using “Common Test” framework, each test execution has a unique node name allowing a higher degree of resources isolation. Is it possible to achieve the same in elixir with ExUnit?
Marked As Solved
leorodriguesrj
I came up with this
work in progress!
# Starting "epmd"
epmd_path = System.find_executable("epmd")
port = Port.open({:spawn_executable, epmd_path}, [ ])
os_pid = Keyword.get(Port.info(port), :os_pid)
# Configuring a "shutdown hook" to stop epmd after everything is done.
# (I'm not particularly proud of this implementation, honestly)
System.at_exit(fn _ -> System.shell("kill -TERM #{os_pid}") end)
# This is a bit of an exageration just to compute a name
{:ok, now} = DateTime.now("Etc/UTC")
now = DateTime.to_unix(now)
cipher = '#{now}'
|> Enum.map(fn c -> c + 49 end)
|> List.to_string()
# Turn this node into a distributed node
{:ok, _} = Node.start(String.to_atom("#{cipher}@testhost"))
# Finally, start the tests
ExUnit.start()
For some reason, I was unable to make correct use of Port.close/1, so I used the kill command to stop epmd. Obviously, this implementation will fail in windows.
Also Liked
LostKobrakai
ExUnit tests may run async to each other, so afaik there is no built in support for something like that. Though I guess nothing would prevent you from creating a case template, which restarts distribution each time and assigns a unique name to the node.
LostKobrakai
Or Node.start/3 and Node.stop/0
lud
I didn’t know those even existed 
@leorodriguesrj To start epmd add {_, 0} = System.cmd("epmd", ["-daemon"]) before ExUnit.start() in test_helper.exs
ityonemo
I wouldn’t use clustering as a strategy for resource segregation. Certainly “actually testing clustering” using test-time clusters (for example using the :slave module) is a thing. But for resource segregation I think “recommended way” to do this is to do it in one node, and take advantage of something like Mox to mock out the contended resource, and in your mock, stub out calls to a process started using ExUnit.start_supervised – this process can be stateful and will automatically have a lifetime that matches the lifetime of your test. Mox is already “a resource that is sharded based on tests” so that could make what you are trying to do WAY easier.
You could also dig deeper and use the Process dictionary, :$caller and :$ancestor keys to manually build resource-shardable subsystems, and make it so that each test has its own checkout of your resource. I built a library around this concept but I don’t currently recommend it.







