Elixir Test Organization
Test organization is grouping related tests and marking them so a run stays easy to read. Groups and marks make a failure point at one part of the code.
Groups keep related tests together
Two describe blocks group one addition test and one subtraction test. The run counts both tests.
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule MathTest do
use ExUnit.Case
describe "addition" do
test "adds two numbers" do
assert 1 + 2 == 3
end
end
describe "subtraction" do
test "subtracts two numbers" do
assert 5 - 2 == 3
end
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")Marks label each test
Each test carries a mark naming its area. Marks do not change the run, so both marked tests pass.
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule MarkedTest do
use ExUnit.Case
@tag area: :math
test "adds" do
assert 2 + 3 == 5
end
@tag area: :words
test "upcases" do
assert String.upcase("ana") == "ANA"
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")A run can leave marked tests out
This run excludes the slow mark. The total still counts the left-out test, and the excluded count names it.
ExUnit.start(seed: 0, auto_run: false, formatters: [], exclude: [slow: true])
defmodule MarkedTest do
use ExUnit.Case
@tag slow: true
test "slow one" do
assert 1 == 1
end
test "fast one" do
assert 2 == 2
end
end
result = ExUnit.run()
IO.puts("total: #{result.total}")
IO.puts("excluded: #{result.excluded}")
IO.puts("failures: #{result.failures}")Example
ExUnit.start(seed: 0, auto_run: false, formatters: [])
defmodule CalcTest do
use ExUnit.Case
describe "addition" do
@tag area: :math
test "adds" do
assert 2 + 3 == 5
end
test "adds zero" do
assert 5 + 0 == 5
end
end
describe "upcasing" do
test "upcases a word" do
assert String.upcase("ana") == "ANA"
end
end
end
result = ExUnit.run()
IO.puts("passed: #{result.total - result.failures}/#{result.total}")Key points
- Describe: a describe block groups tests about one thing under one name.
- Tag: a tag marks a test, so a run can include or exclude marked tests.
- Layout: a test file starts ExUnit, then defines one test module, then runs and prints counts.
- One part: each describe block covers one part, so a failure points at one area.
- Marking: a tag sits above the test it marks, written as a module attribute line.
In this example, one test module holds two describe blocks, one for addition with two tests and one for upcasing with one test. One addition test also carries an area mark, and all three tests pass.
Note
tags are labels only, so a marked test still runs unless the run excludes its tag.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What is a describe block for?