Elixir Async Tests
Async tests are tests that ExUnit may run at the same time as other tests. They suit tests that do not share changing state.
An async module holds ordinary tests
ExUnit starts with a fixed seed and no formatters. The module is marked async, and the script prints only its own counts.
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule AddTest do
use ExUnit.Case, async: true
test "adds two numbers" do
assert 1 + 2 == 3
end
test "adds zero" do
assert 5 + 0 == 5
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")Two async modules share one run
Each module is marked async on its own. The single run counts the tests from both modules.
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule TripleTest do
use ExUnit.Case, async: true
test "triples a number" do
assert 3 * 4 == 12
end
end
defmodule HalfTest do
use ExUnit.Case, async: true
test "halves a number" do
assert div(10, 2) == 5
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")The run result carries the counts
The result of ExUnit.run is a map. The script prints its total and its failures from that map.
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule OneTest do
use ExUnit.Case, async: true
test "checks one fact" do
assert String.upcase("ana") == "ANA"
end
end
result = ExUnit.run()
IO.puts("total: #{result.total}")
IO.puts("failures: #{result.failures}")Example
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule MathTest do
use ExUnit.Case, async: true
test "adds" do
assert 2 + 3 == 5
end
test "multiplies" do
assert 2 * 3 == 6
end
end
defmodule WordTest do
use ExUnit.Case, async: true
test "upcases" do
assert String.upcase("ana") == "ANA"
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")Key points
- ExUnit: start ExUnit once with ExUnit.start before any test module is defined.
- Async: a test module marked async may run at the same time as other async modules.
- Seed: a fixed seed makes the test order the same on every run.
- Formatters: an empty formatter list stops ExUnit from printing its own report.
- Counts: ExUnit.run returns a map with total and failures, so the script prints its own counts.
In this example, ExUnit starts with a fixed seed and no formatters, then two async modules are defined, one with two math tests and one with one word test. ExUnit.run runs all three tests, and the script prints the passed count from the result map.
Note
async tests must not share changing state, since they may run at the same time.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does marking a test module async mean?