Parallel EUnit Testing
Summary:
By default, EUnit runs tests sequentially. Large test suites benefit from parallel execution. You can enable this in the test code itself or globally via build tool configuration.
Introduction
Running tests in parallel reduces total execution time. EUnit provides a wrapper to dispatch tests to worker processes.
To run a group of tests in parallel within the source code, wrap the test representation in a tuple starting with the inparallel atom.
my_parallel_test_() ->
{inparallel,
[test_one(),
test_two(),
test_three()]}.
Each test in the list runs in its own process. This is for independent unit tests that do not share state.
Rebar3 Configuration
You can enable parallel execution globally in your rebar.config file. This allows you to keep your test files clean of EUnit-specific parallel wrappers.
Add the parallel option to eunit_opts in rebar.config:
{eunit_opts, [verbose, inparallel]}.
You can provide a boolean to use a default worker count or an integer to specify a limit
{eunit_opts, [verbose, {parallel, 8}]}.
Alternatively, you can trigger parallel execution from the command line without modifying any files with the command:
$ rebar3 eunit --parallel=8
This approach is often better for CI environments where you want to maximize resource usage without hardcoding those limits into the repository.
Parallel Fixtures
Using setup or foreach with inparallel requires attention to process ownership. The setup and cleanup functions run in the main EUnit process, while the tests run in worker processes.
If your setup creates a process that links to the caller, that process may die when the setup function finishes rather fthan staying alive for the parallel test workers.
parallel_fixture_test_() ->
{foreach,
fun setup/0,
fun cleanup/1,
[{inparallel, [fun test_a/1, fun test_b/1]}]}.
Specifying which tests can be run in parallel allows eunit itself to run tests without having to fire up rebar.
eunit:test([my_module1, my_module2]).
This may be necessary in environments which deployments may not have rebar3 or a 'shell' to run these tests, I did a quick build/config on Crazierl which didnt have a real shell for the OS.
Conclusion
Parallel testing is a simple way to optimize your development loop. Choose between inline wrappers for specific suites or Rebar3 configuration for global application.