ExUnited v0.1.3 ExUnited View Source
This module facilitates spawning nodes within tests.
For using ExUnited
, the two essential functions are:
ExUnited.spawn/2
- Spawns (Mix.Config
configured, additional code loaded, supervising) nodesExUnited.teardown/0
- Kills the spawned nodes and it also cleans up their generated files
The most simplest setup
Nodes can be specified as a list of atoms, just like in the following example.
Their node names will be :"bruce@127.0.0.1"
and :"clark@127.0.0.1"
respectively).
Please do not forget to invoke ExUnited.teardown/0
at the on_exit
hook.
setup do
{:ok, spawned} = ExUnited.spawn([:bruce, :clark])
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
"Partially versus Fully connected" and/or "Verbose" spawned nodes
As a second argument, you can pass a list of atoms for the options:
:connect
- iftrue
a "fully connected" node will be spawned (see theerl -connect_all
flag for more information). Defaults tofalse
:verbose
- iftrue
the STDOUT of the spawned node will be printed. Defaults tofalse
See ExUnited.spawn/2
for more information.
setup do
{:ok, spawned} = ExUnited.spawn([:roy], [:connect, :verbose])
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
Which results in the following when running tests:
PME-Legend ~/S/ex_united:master> mix test test/ex_united/supervised_test.exs:140
Excluding tags: [:test]
Including tags: [line: "140"]
iex(roy@127.0.0.1)> Compiling 1 file (.ex)
iex(roy@127.0.0.1)> Generated void app
iex(roy@127.0.0.1)> Interactive Elixir (1.10.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(roy@127.0.0.1)1>
.
Finished in 0.9 seconds
2 tests, 0 failures, 1 excluded
Exclude certain dependencies within spawned nodes
You can exclude certain (Mix) dependencies from your spawned nodes by for instance
adding exclude: [:inch_ex]
to the options. This can significantly improve
the speed of your tests.
setup do
{:ok, spawned} = ExUnited.spawn([:bruce, :clark], [:verbose, exclude: [:inch_ex]])
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
The following dependencies are excluded by default:
:credo
:dialyxir
:ex_doc
:ex_united
:excoveralls
Configuring the spawned nodes
Aside from the list of atoms, you can also specify nodes as a keyword list in case you want to configure them. The following options are available:
:code_paths
- a list of directories that will be included:exclude
- a list of dependencies that will be excluded:supervise
- the child spec(s) used for supervisioning
Including additional code
It would be a best practice to create a directory called test/nodes
in which
you put a directory containing code for a specific spawned node. Please note that
the file called config.exs
is supported for Mix.Config
:
setup do
{:ok, spawned} =
ExUnited.spawn(
eric: [
code_paths: [
"test/nodes/cantona"
]
]
)
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
See test/ex_united/supervised_test.exs with its corresponding test/nodes/ronaldo as an example.
Exclude certain dependencies for a specific spawned node
Add the :exclude
list as follows:
setup do
{:ok, spawned} =
ExUnited.spawn(
bruce: [
code_paths: [
"test/nodes/bruce"
],
exclude: [
:my_unused_dependency
],
supervise: [MyAwesomeGenServer]
],
clark: [
code_paths: [
"test/nodes/clark"
],
supervise: [MyOtherAwesomeGenServer]
]
)
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
Add supervisioning
Childspecs should be the same argument as if you are adding them to your classic
<app>/application.ex
file:
setup do
{:ok, spawned} =
ExUnited.spawn(
bruce: [
code_paths: [
"test/nodes/bruce"
],
supervise: [MyAwesomeGenServer]
],
clark: [
code_paths: [
"test/nodes/clark"
],
supervise: [MyOtherAwesomeGenServer]
]
)
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
Pay attention that functions within childspecs should be quoted.
setup do
{:ok, spawned} =
ExUnited.spawn(
[
roy: [
code_paths: [
"test/nodes/keane"
],
supervise: [
{
Roy,
talk:
quote do
fn
1 -> "Hi, I am Roy Keane"
2 -> "I am keen as mustard"
3 -> "I like to be peachy keen"
end
end
}
]
]
],
[:verbose]
)
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
Easily assert and refute within the context of spawned nodes
To seemlessly execute assertions and refutations within spawned nodes, you can
setup your test module by either using ExUnited.Case
instead of ExUnit.Case
:
defmodule MyNodesTest do
use ExUnited.Case
end
Or by importing the ExUnited.Case
module:
defmodule MyNodesTest do
use ExUnit.Case
import ExUnited.Case
end
Writing assertions and refutations within the context of a certain spawned is
pretty straight forward with the use of the ExUnited.Case.as_node/2
function
as if you are writing your class assert
and/or refute
statements:
defmodule MyNodesTest do
use ExUnited.Case
setup do
{:ok, spawned} = ExUnited.spawn([:bruce, :clark])
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
test "assertions and refutations within node contexts", spawned do
bruce = get_in(spawned, [:bruce, :node])
as_node(bruce) do
assert :"bruce@127.0.0.1" = Node.self()
refute :"clark@127.0.0.1" == Node.self()
end
as_node(:clark) do
assert :"clark@127.0.0.1" = Node.self()
refute :"bruce@127.0.0.1" == Node.self()
end
end
end
See ExUnited.Case.as_node/2
for more information.
Link to this section Summary
Functions
Spawns nodes for testing purposes. Supervised applications are supported.
Starts both the ExUnit
and ExUnited.Spawn
gen servers. This should replace
the default ExUnit.start()
invocation in the test helper file.
Should be invoked at the end of a test which spawned nodes. This kills the
nodes and it also cleans up their generated files located in
/tmp/[NODENAME]-{config,mix}.exs
.
Link to this section Functions
spawn(nodes, opts \\ [])
View Sourcespawn([node()] | [{node(), keyword()}], [atom()]) :: {:ok, [ExUnited.Node.t()]}
Spawns nodes for testing purposes. Supervised applications are supported.
Nodes can be either specified as a list of atoms (such as [:bruce, :clark]
for
instance; the node names will be :"bruce@127.0.0.1"
and :"clark@127.0.0.1"
respectively) or as a keyword list (in case of configuring the spawned node).
The following options are available to configure nodes:
:code_paths
- a list of directories that will be included (please note that the file calledconfig.exs
is supported forMix.Config
):exclude
- a list of dependencies that will be excluded:supervise
- the child spec(s) used for supervisioning
Aside from options for configuring individual nodes, as a second argument, you can pass a list of atoms for the following:
:connect
- iftrue
a "fully connected" node will be spawned (see theerl -connect_all
flag for more information). Defaults tofalse
:verbose
- iftrue
the STDOUT of the spawned node will be printed. Defaults tofalse
And last but not least, you can exclude certain (Mix) dependencies from your
spawned nodes by adding exclude: [:inch_ex]
to the options. This can
significantly improve the speed of your tests.
The following dependencies are excluded by default:
:credo
:dialyxir
:ex_doc
:ex_united
:excoveralls
Examples
The most simplest setup:
setup do
{:ok, spawned} = ExUnited.spawn([:bruce, :clark])
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
Spawn "fully connected" nodes and print all their STDOUT in the console:
setup do
{:ok, spawned} = ExUnited.spawn([:bruce, :clark], [:connect, :verbose])
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
Exclude certain dependencies for all nodes:
setup do
{:ok, spawned} = ExUnited.spawn([:bruce, :clark], [:verbose, exclude: [:inch_ex]])
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
A configured nodes setup:
setup do
{:ok, spawned} =
ExUnited.spawn(
bruce: [
code_paths: [
"test/nodes/bruce"
],
supervise: [MyAwesomeGenServer]
],
clark: [
code_paths: [
"test/nodes/clark"
],
supervise: [MyOtherAwesomeGenServer]
]
)
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
Exclude certain dependencies for a specific spawned node:
setup do
{:ok, spawned} =
ExUnited.spawn(
bruce: [
code_paths: [
"test/nodes/bruce"
],
exclude: [
:my_unused_dependency
],
supervise: [MyAwesomeGenServer]
],
clark: [
code_paths: [
"test/nodes/clark"
],
supervise: [MyOtherAwesomeGenServer]
]
)
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
Also note that functions within childspecs should be quoted.
setup do
{:ok, spawned} =
ExUnited.spawn(
[
roy: [
code_paths: [
"test/nodes/keane"
],
supervise: [
{
Roy,
talk:
quote do
fn
1 -> "Hi, I am Roy Keane"
2 -> "I am keen as mustard"
3 -> "I like to be peachy keen"
end
end
}
]
]
],
[:verbose]
)
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
Starts both the ExUnit
and ExUnited.Spawn
gen servers. This should replace
the default ExUnit.start()
invocation in the test helper file.
# test/test_helper.exs
ExUnited.start()
As of version 0.1.2
, you can also start ExUnit
yourself explicitly and add
ExUnited.start(false)
instead:
# test/test_helper.exs
ExUnit.start()
ExUnited.start(false)
Should be invoked at the end of a test which spawned nodes. This kills the
nodes and it also cleans up their generated files located in
/tmp/[NODENAME]-{config,mix}.exs
.
Example
defmodule MyNodesTest do
use ExUnit.Case
setup do
{:ok, spawned} = ExUnited.spawn([:bruce, :clark])
on_exit(fn ->
ExUnited.teardown()
end)
spawned
end
test "does awesome stuff with spawned nodes", spawned do
# a lot of awesome assertions and refutations
end
end