Testing with ExUnit
Assertions: assert, refute, assert_raise, assert_in_delta, assert_receive, assert_received, refute_receive, catch_throw, catch_exit, flunk.
27.1 Basics
Assertions: assert, refute, assert_raise, assert_in_delta, assert_receive, assert_received, refute_receive, catch_throw, catch_exit, flunk. Pattern assertions: assert {:ok, %{id: id}} = create().
# test/math_test.exs
defmodule MathTest do
use ExUnit.Case, async: true
doctest Math
test "sum/2 adds numbers" do
assert Math.sum(1, 2) == 3
end
test "raises on bad input" do
assert_raise ArithmeticError, fn -> Math.sum(1, :a) end
end
describe "square/1" do
test "positive" do
assert Math.square(3) == 9
refute Math.square(3) == 10
end
end
end27.2 Setup and context
setup do
user = %User{name: "Ann"}
{:ok, user: user}
end
setup :create_account # named setup function
setup_all do ... end # once per module
test "uses context", %{user: user} do
assert user.name == "Ann"
end
on_exit(fn -> cleanup() end)27.3 Tags & filtering
test/test_helper.exs: ExUnit.start(exclude: [:integration]).
@tag :slow
@tag timeout: 120_000
@moduletag :integration
@tag :skipmix test --only slow
mix test --exclude integration27.4 Doctests
@doc """
Adds two numbers.
iex> Math.sum(1, 2)
3
"""
def sum(a, b), do: a + b27.5 Testing processes
test "receives message" do
send(self(), {:hello, 1})
assert_receive {:hello, n} when n > 0, 500
end
test "genserver" do
pid = start_supervised!({Counter, 0})
Counter.increment(pid)
assert Counter.value(pid) == 1
end27.6 Mocks with Mox
# define a behaviour, then in test_helper.exs:
Mox.defmock(MyApp.HTTPMock, for: MyApp.HTTPClient)
# in test:
import Mox
setup :verify_on_exit!
test "fetches" do
expect(MyApp.HTTPMock, :get, fn "url" -> {:ok, "body"} end)
assert MyApp.fetch("url") == {:ok, "body"}
end27.7 Property-based testing
use ExUnitProperties # stream_data
property "reverse twice is identity" do
check all list <- list_of(integer()) do
assert list |> Enum.reverse() |> Enum.reverse() == list
end
end27.8 Coverage & parameterised tests
mix test --cover; excoveralls for reports. 1.18+ supports parameterize: on ExUnit.Case to run a module with different parameters.