ExUnit v1.5.1 ExUnit.Callbacks View Source
Defines ExUnit callbacks.
This module defines both setup_all
and setup
callbacks, as well as
the on_exit/2
, start_supervised/2
and stop_supervised/1
functions.
The setup callbacks are defined via macros and each one can optionally
receive a map with metadata, usually referred to as context
. The
callback may optionally put extra data into the context
to be used in
the tests.
The setup_all
callbacks are invoked only once per module, before any
test runs. All setup
callbacks are run before each test. No callback
runs if the test case has no tests or all tests have been filtered out.
start_supervised/2
is used to start processes under a supervisor. The
supervisor is linked to the current test process. The supervisor as well
as all child processes are guaranteed to terminate before any on_exit/2
callback runs.
on_exit/2
callbacks are registered on demand, usually to undo an action
performed by a setup callback. on_exit/2
may also take a reference,
allowing callback to be overridden in the future. A registered on_exit/2
callback always runs, while failures in setup
and setup_all
will stop
all remaining setup callbacks from executing.
Finally, setup_all
callbacks run in a separate process per module, while
all setup
callbacks run in the same process as the test itself. on_exit/2
callbacks always run in a separate process, as implied by their name. The
test process always exits with reason :shutdown
, which means any process
linked to the test process will also exit, although asynchronously. Therefore
it is preferred to use start_supervised/2
to guarantee synchronous termination.
Here is a run down of the life-cycle of the test process:
- the test process is spawned
- it runs
setup/2
callbacks - it runs the test itself
- it stops all supervised processes
- the test process exits with reason
:shutdown
on_exit/2
callbacks are executed in a separate process
Context
If you return a keyword list, a map, or {:ok, keywords | map}
from
setup_all
, the keyword list/map will be merged into the current context and
be available in all subsequent setup_all
, setup
, and the test
itself.
Similarly, returning a keyword list, map, or {:ok, keywords | map}
from
setup
means that the returned keyword list/map will be merged into the
current context and be available in all subsequent setup
and the test
itself.
Returning :ok
leaves the context unchanged (both in setup
and setup_all
callbacks).
Returning anything else from setup_all
will force all tests to fail,
while a bad response from setup
causes the current test to fail.
Examples
defmodule AssertionTest do
use ExUnit.Case, async: true
# "setup_all" is called once per module before any test runs
setup_all do
IO.puts "Starting AssertionTest"
# No context is returned here
:ok
end
# "setup" is called before each test
setup do
IO.puts "This is a setup callback for #{inspect self()}"
on_exit fn ->
IO.puts "This is invoked once the test is done. Process: #{inspect self()}"
end
# Returns extra metadata to be merged into context
[hello: "world"]
end
# Same as above, but receives the context as argument
setup context do
IO.puts "Setting up: #{context.test}"
:ok
end
# Setups can also invoke a local or imported function that returns a context
setup :invoke_local_or_imported_function
test "always pass" do
assert true
end
test "uses metadata from setup", context do
assert context[:hello] == "world"
end
defp invoke_local_or_imported_function(context) do
[from_named_setup: true]
end
end
Link to this section Summary
Functions
Defines a callback that runs once the test exits
Defines a callback to be run before each test in a case
Defines a callback to be run before each test in a case
Defines a callback to be run before all tests in a case
Defines a callback to be run before all tests in a case
Starts a child process under the test supervisor
Stops a child process started via start_supervised/2
Link to this section Functions
Defines a callback that runs once the test exits.
callback
is a function that receives no arguments and
runs in a separate process than the caller.
on_exit/2
is usually called from setup
and setup_all
callbacks, often to undo the action performed during setup
.
However, on_exit/2
may also be called dynamically, where a
reference can be used to guarantee the callback will be invoked
only once.
Defines a callback to be run before each test in a case.
Examples
setup context do
[conn: Plug.Conn.build_conn()]
end
Defines a callback to be run before all tests in a case.
Examples
setup_all context do
[conn: Plug.Conn.build_conn()]
end
start_supervised(Supervisor.child_spec() | module() | {module(), term()}, keyword()) :: Supervisor.on_start_child()
Starts a child process under the test supervisor.
It expects a child specification or a module, similar to the ones
given to Supervisor.start_link/2
. For example, if your application
starts a supervision tree by running:
Supervisor.start_link([MyServer, {OtherSupervisor, ...}], ...)
You can start those processes under test in isolation by running:
start_supervised(MyServer)
start_supervised({OtherSupervisor, :initial_value})
A keyword list can also be given if there is a need to change the child specification for the given child process:
start_supervised({MyServer, :initial_value}, restart: :temporary)
See the Supervisor
module for a discussion on child specifications
and the available specification keys.
The advantage of starting a process under the test supervisor is that
it is guaranteed to exit before the next test starts. Furthermore,
because the child process is supervised, it will be restarted in case
of crashes according to the :restart
strategy in the child
specification, even if stopped manually. Therefore, to guarantee a
process started with start_supervised/2
terminates without restarts,
see stop_supervised/1
.
This function returns {:ok, pid}
in case of success, otherwise it
returns {:error, reason}
.
stop_supervised(id :: term()) :: :ok | {:error, :not_found}
Stops a child process started via start_supervised/2
.
This function expects the id
in the child specification.
For example:
{:ok, _} = start_supervised(MyServer)
:ok = stop_supervised(MyServer)
It returns :ok
if there is a supervised process with such
id
, {:error, :not_found}
otherwise.