I’ve been using Elixir for a while and only today realized that the default async
value for use ExUnit.Case
is false
.
It seems I’m not the only one who thought this was the case: Default value for ExUnit.Case async
Anyways, I spent some time looking at the code of ExUnit.Case
as well as ExUnit.CaseTemplate
, and was able to figure out a way to make async: true
the default. So I thought I’d share it here:
defmodule MyApp.Case do
@moduledoc false
use ExUnit.CaseTemplate
# Override `ExUnit.CaseTemplate.__using__` so we can manipulate opts and
# default to `async: true`.
#
# For reference, see the original `defmacro __using__` that is injected
# by ExUnit.CaseTemplate:
# https://github.com/elixir-lang/elixir/blob/main/lib/ex_unit/lib/ex_unit/case_template.ex#L142
defmacro __using__(opts) do
parent = ExUnit.CaseTemplate.__proxy__(__MODULE__, default_async_true(opts))
injected_frontmatter = frontmatter()
{:__block__, [], [parent, injected_frontmatter]}
end
defp default_async_true(opts) do
case Keyword.fetch(opts, :async) do
{:ok, false} ->
# If `async: false` is specified, leave opts alone.
opts
_ ->
# If `async: false` is not specified, set `async: true`
Keyword.put(opts, :async, true)
end
end
defp frontmatter do
quote do
# Here's where you'd put useful aliases that normally go in `using do`
end
end
end
Now if you do use MyApp.Case
, it’ll get async: true
by default!