# test/test_helper.exs
ExUnit.start()
Mix will load the test_helper.exs
file before executing the tests.
use ExUnit.Case, async: true
:async - configures tests in this module to run concurrently with tests in other modules. Tests in the same module do not run concurrently. It should be enabled only if tests do not change any global state. Defaults to false.
without context
test "true is equal to true" do
assert true == true
end
All tests receive a context as an argument. There are some ways to build the context before run all test cases in individual test module.
with context
test "unit test case with context", context do
IO.inspect(context, label: "The context is:")
assert true
end
- timeout
- capture_log
- user-defined tag
This default can be overridden by @tag capture_log: false or @moduletag capture_log: false.
test "unit test assert" do
assert true
assert 1
assert ""
assert !nil
assert !false
assert %{} = %{a: :a, b: :b}
assert %{} != %{a: :a, b: :b}
end
test "unit test assert_raise" do
assert_raise ArithmeticError, "bad argument in arithmetic expression", fn -> 1 + :a end
assert_raise RuntimeError, fn -> raise "oops" end
end
test "unit test assert_receive" do
main_pid = self()
spawn(fn ->
Process.sleep(1_000)
send(main_pid, {:ok, self()})
end)
assert_receive {:ok, _}, 2_000
end
test "unit test assert_received" do
send(self(), {:ok, self()})
assert_received {:ok, _}
end
exit/throw
test "unit test assertions catch_*" do
assert catch_exit(exit 1) == 1
assert catch_throw(throw 1) == 1
end
Something about error raising exceptions in EVM
test "unit test refute" do
refute nil
refute false
end
There are many usual callbacks for ExUnit:
- setup
- setup_all
- on_exit
- start_supervised
- stop_supervised
Build context for test case.
test "unit test case with context", context do
IO.inspect(context, label: "The context is:")
assert true
end
The context
is a map, can be used in each test case.
- Optionally receive a map with test state and metadata.
- All
setup
callbacks are run before each test. - Return
keyword list
/map
/{:ok, keywords | map}
/:ok
.
setup do
# IO.puts("Generate random number 1 in setup")
[random_num_1: Enum.random(1..1_000)]
end
setup :generate_random_number_2
defp generate_random_number_2(context) do
# IO.puts("Generate random number 2 in setup")
context
|> Map.put(:random_num_2, Enum.random(1..1_000))
end
test "setup case 1", %{random_num_1: random_num_1, random_num_2: random_num_2} = _context do
IO.puts("The random numbers in case #1 are: {#{random_num_1}, #{random_num_2}}")
assert true
end
test "setup case 2", %{random_num_1: random_num_1, random_num_2: random_num_2} = _context do
IO.puts("The random numbers in case #2 are: {#{random_num_1}, #{random_num_2}}")
assert true
end
- Optionally receive a map with test state and metadata.
- Return
keyword list
/map
/{:ok, keywords | map}
/:ok
. - Invoked only once per module.
setup_all do
[setup_all_random_num_1: Enum.random(1..1_000)]
end
setup_all :generate_setup_all_random_number_2
defp generate_setup_all_random_number_2(context) do
context
|> Map.put(:setup_all_random_num_2, Enum.random(1..1_000))
end
test "setup_all case 1", %{setup_all_random_num_1: num_1, setup_all_random_num_2: num_2} do
IO.puts("The random numbers in case setup_all #1 are: {#{num_1}, #{num_2}}")
end
test "setup_all case 2", %{setup_all_random_num_1: num_1, setup_all_random_num_2: num_2} do
IO.puts("The random numbers in case setup_all #2 are: {#{num_1}, #{num_2}}")
end
using mock library
test "unit test mock with one mocked module" do
with_mock(ModuleA, cross_gwf: fn -> :ok end, kill_gwf: fn _ -> true end) do
assert :ok == ModuleA.cross_gwf()
assert true == ModuleA.kill_gwf(nil)
end
end
test_with_mock "unit test mock using macro test_with_mock", ModuleA, [],
cross_gwf: fn -> :ok end,
kill_gwf: fn _ -> true end do
assert :ok == ModuleA.cross_gwf()
assert true == ModuleA.kill_gwf(nil)
end
test "unit test mock with multi-mocked modules" do
with_mocks([
{ModuleA, [], [cross_gwf: fn -> :ok end, kill_gwf: fn _ -> true end]},
{ModuleB, [], [cross_gwf: fn -> :ok end, kill_gwf: fn _ -> true end]}
]) do
assert :ok == ModuleA.cross_gwf()
assert true == ModuleA.kill_gwf(nil)
assert :ok == ModuleB.cross_gwf()
assert true == ModuleB.kill_gwf(nil)
end
end
setup_with_mocks([
{ModuleA, [], [cross_gwf: fn -> 1 end, kill_gwf: fn _ -> 2 end]},
{ModuleB, [], [cross_gwf: fn -> 1 end, kill_gwf: fn _ -> 2 end]}
]) do
:ok
end
test "unit test mock use setup with setup with mocks modulea" do
assert 1 == ModuleA.cross_gwf()
assert 2 == ModuleA.kill_gwf(nil)
end
test "unit test mock use setup with setup with mocks moduleb" do
assert 1 == ModuleB.cross_gwf()
assert 2 == ModuleB.kill_gwf(nil)
end
test "unit test for reversed to codes" do
assert :"1" == LearnExunit.to_to_atom(build_params_for_func("1"))
assert :a == LearnExunit.to_to_atom(build_params_for_func("a"))
assert :"1" == LearnExunit.to_atom("1")
assert :a == LearnExunit.to_atom("a")
end