ExUnitFixtures v0.3.1 ExUnitFixtures

A library for declaring & using test fixtures in ExUnit.

For an overview of it’s purpose see the README.

To use ExUnitFixtures we need to start it. Add the following code to your test_helpers.exs:

ExUnitFixtures.start

This starts the ExUnitFixtures application and imports any fixtures.exs files that are found in the test directory heiararchy. See ExUnitFixtures.start/1 for more details.

Next you should:

  1. Add use ExUnitFixtures to your test cases (before use ExUnit.Case)
  2. Define some fixtures using deffixture/3
  3. Tag some tests with @tag fixtures: [:your_fixtures_here]

The tagged tests will automatically have all the requested fixtures injected into their context. For example:

iex(2)> defmodule MyTests do
...(2)>   use ExUnitFixtures
...(2)>   use ExUnit.Case
...(2)>
...(2)>   deffixture my_model do
...(2)>     # Create a model somehow...
...(2)>     %{test: 1}
...(2)>   end
...(2)>
...(2)>   @tag fixtures: [:my_model]
...(2)>   test "that we have some fixtures", context do
...(2)>     assert context.my_model.test == 1
...(2)>   end
...(2)> end
iex(3)> Module.defines?(MyTests, :create_my_model)
true

Fixtures with dependencies

Fixtures can also depend on other fixtures by naming a parameter after that fixture. For example, if you needed to setup a database instance before creating some models:

iex(4)> defmodule MyTests2 do
...(4)>   use ExUnitFixtures
...(4)>   use ExUnit.Case
...(4)>
...(4)>   deffixture database do
...(4)>     # set up the database somehow...
...(4)>   end
...(4)>
...(4)>   deffixture my_model(database) do
...(4)>     # use the database to insert a model
...(4)>   end
...(4)>
...(4)>   @tag fixtures: [:my_model]
...(4)>   test "something", %{my_model: my_model} do
...(4)>     # Test something with my_model
...(4)>   end
...(4)> end
iex(5)> Module.defines?(MyTests2, :create_database)
true
iex(6)> Module.defines?(MyTests2, :create_my_model)
true

In the sample above, we have 2 fixtures: one which creates the database and another which inserts a model into that database. The test function depends on my_model which depends on the database. ExUnitFixtures knows this, and takes care of setting up the database and passing it in to my_model.

Fixture Scoping

Fixtures may optionally be provided with a scope:

  • :test scoped fixtures will be created before a test and deleted afterwards. This is the default scope for a fixture.
  • :module scoped fixtures will be created at the start of a test module and passed to every single test in the module.

For details on how to specify scopes, see deffixture/3.

Tearing down Fixtures

If you need to do some teardown work for a fixture you can use the ExUnit on_exit function:

iex(8)> defmodule TestWithTearDowns do
...(8)>   use ExUnitFixtures
...(8)>   use ExUnit.Case
...(8)>
...(8)>   deffixture database do
...(8)>     # Setup the database
...(8)>     on_exit fn ->
...(8)>       # Tear down the database
...(8)>       nil
...(8)>     end
...(8)>   end
...(8)> end
iex(9)> Module.defines?(MyTests2, :create_database)
true

Sharing Fixtures Amongst Test Cases.

It is possible to share fixtures among test cases by declaring that module a fixture module. See ExUnitFixtures.FixtureModule for more details.

When started, ExUnitFixtures automatically loads any fixtures.exs files it finds in the test directory hierarchy. Any test or fixture module will also automatically import any fixtures defined in fixtures.exs files in it’s current or parent directories. This allows ExUnitFixtures to provide a powerful yet simple method of sharing fixtures amongst tests in a directory heirarchy. See ExUnitFixtures.AutoImport for more details.

Summary

Functions

Loads all files it finds matching fixture_pattern into the VM

Starts the ExUnitFixtures application

Macros

Defines a fixture local to a test module

Functions

load_fixture_files(fixture_pattern \\ "test/**/fixtures.exs")

Specs

load_fixture_files(Regex.t) :: nil

Loads all files it finds matching fixture_pattern into the VM.

start(opts \\ [])

Starts the ExUnitFixtures application.

By default this will also look for any fixtures.exs files in the test directory and load them into the VM so we can use the fixtures contained within. This can be controlled by the auto_load option described below.

The keyword list opts may be provided to override any of the default options.

Options

  • auto_import controls whether tests & fixture modules should automatically import fixtures from fixtures.exs files in their directory tree. This is true by default
  • auto_load controls whether ExUnitFixtures should automatically load fixtures.exs files it finds in the test directory tree on startup. This is true by default.

Macros

deffixture(arg, opts \\ [], body)

Defines a fixture local to a test module.

This is intended to be used much like a def statement:

deffixture my_fixture do
  "my_fixture_text"
end

A fixture may optionally depend on other fixtures. This is done by creating a fixture that accepts parameters named after other fixtures. These fixtures will automatically be run and injected as parameters to the current fixture. For example:

deffixture database do
  %{database: true}
end

deffixture model(database) do
  %{model: true}
end

Fixture Options

Fixtures can accept various options that control how they are defined:

deffixture database, scope: :module do
  %{database: true}
end

These options are supported:

  • scope controls the scope of fixtures. See Fixture Scoping for details.
  • Passing autouse: true will cause a fixture to be passed to every test in the module.