Elixir Test Helpers
A test helper is a shared module that holds setup and checks used by more than one test module. One helper replaces copied setup in every test that uses it.
A helper builds the same starting state
One helper function returns the same sample list. Every test that imports it starts from that list.
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule ListHelper do
def sample, do: [3, 1, 2]
end
defmodule SampleTest do
use ExUnit.Case
import ListHelper
test "helper supplies the sample" do
assert sample() == [3, 1, 2]
assert length(sample()) == 3
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")A helper holds a shared check
The shared check asserts sorted order and returns the length. Tests call it instead of repeating the assertion.
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule ListHelper do
import ExUnit.Assertions
def check_sorted(list) do
assert list == Enum.sort(list)
length(list)
end
end
defmodule SortedTest do
use ExUnit.Case
import ListHelper
test "helper checks sorted order" do
assert check_sorted([1, 2, 3]) == 3
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")Two test modules reuse one helper
Both modules import the same helper. Neither module copies the sample list.
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule ListHelper do
def sample, do: [3, 1, 2]
end
defmodule FirstTest do
use ExUnit.Case
import ListHelper
test "first module uses the sample" do
assert sample() == [3, 1, 2]
end
end
defmodule SecondTest do
use ExUnit.Case
import ListHelper
test "second module uses the sample" do
assert length(sample()) == 3
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")Example
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule ListHelper do
import ExUnit.Assertions
def sample, do: [3, 1, 2]
def sorted_sample, do: Enum.sort(sample())
def check_sorted(list) do
assert list == Enum.sort(list)
length(list)
end
end
defmodule SortedSampleTest do
use ExUnit.Case
import ListHelper
test "sorted sample passes the shared check" do
assert check_sorted(sorted_sample()) == 3
end
end
defmodule OriginalSampleTest do
use ExUnit.Case
import ListHelper
test "original sample stays unchanged" do
assert sample() == [3, 1, 2]
assert sorted_sample() == [1, 2, 3]
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")Key points
- Test helper: a shared module that holds setup and checks used by more than one test module.
- Shared setup: one function that builds the same starting state for every test that needs it.
- Shared check: one function that asserts the same result in several tests.
- Import: a way to bring a helper's functions into a test module without copying them.
- Single change: fixing the helper once fixes every test that uses it.
In this example, ListHelper supplies a sample list, a sorted version of it, and a shared sorted check. The first test module checks the sorted sample with the shared check. The second test module checks that the original sample is unchanged and that the sorted sample is in order.
Note
a helper holds test setup and checks, not the code being tested.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Why move shared setup into a test helper?