Current section
Files
Jump to
Current section
Files
lib/doctest_setup.ex
defmodule DoctestSetup do
@moduledoc """
Defines doctest setup callbacks.
Typically doctests work best for stateless functions. Including setup in the doctetst itself can
sacrifice readability. DoctestSetup lets us move that setup out of our doctests and into our test
cases.
"""
defmacro __using__(_opts) do
quote do
import unquote(__MODULE__), only: [doctest_setup: 1, doctest_setup: 2]
@before_compile unquote(__MODULE__.Meta)
end
end
@doc """
Defines a callback to be run before doctests, matching on the provided options.
This macro builds on `ExUnit.Callbacks.setup/2` callbacks, so blocks should return the values
described in the [Context](https://hexdocs.pm/ex_unit/ExUnit.Callbacks.html#module-context)
section of the `ExUnit.Callbacks` docs.
The same doctest can be setup by multiple `doctest_setup` blocks.
## Options
The options listed are matched upon, so we can either pass in concrete values or match values out.
Any doctests not matching on the provided options are skipped by the setup block.
- `:arity` - The arity of the target function. For moduledoc doctests, this will be `nil`.
- `:context` - The context of the doctest. See
[Context](https://hexdocs.pm/ex_unit/ExUnit.Callbacks.html#module-context).
- `:module` - The module of the target function.
- `:name` - The name of the target function. For moduledoc doctests, this will be `nil`.
- `:ordinal` - Which doctest in the doctstring to setup. The first doctest in each docstring is
`0`, and each subsequent doctest's ordinal is 1 greater than the previous.
## Example
defmodule MyAppTest do
use ExUnit.Case, async: true
use DoctestSetup
doctest MyApp
doctest_setup name: :hello do
# do something stateful
:ok
end
doctest_setup name: name, arity: arity do
# do something with name and arity
[value: value]
end
end
"""
defmacro doctest_setup(opts \\ [], block)
defmacro doctest_setup(opts, do: block) do
check_for_ex_unit!(__CALLER__)
quote do
setup context do
with %{test_type: :doctest} <- context,
%{unquote_splicing(opts)} <- __doctest_setup_meta__(context) do
unquote(block)
else
_ ->
:ok
end
end
end
end
defp check_for_ex_unit!(env) do
unless {:setup, 2} in Keyword.get(env.macros, ExUnit.Callbacks, []) do
raise __MODULE__.Error
end
end
end