I found it is possible to get pretty good test coverage (near 100%) using __after_compile__/2 in combination with assert_raise/2 in tests.
test "some aspect of my macro" do
assert_raise SomeError, fn ->
defmodule Dummy do
use MyMacro, option: "testable"
end
end
end
Make options available (for example using a module attribute) to be able to validate after compilation.
defmacro __using__(opts) do
option = Keyword.fetch!(opts, :option)
quote do
@__option__ unquote(option)
@after_compile unquote(__MODULE__)
# implementation
end
end
def __after_compile__(env, _bytecode) do
option = Module.get_attribute(env.module, :__option__)
# validate option
# maybe raise exception, assert_raise in test
# when option is a capture, run it.
end
@LostKobrakai while macros are “special functions” these are still functions and with some tricks (see above) you can test them and get coverage for them without problems.
Though I agree for the most part I do like to make sure that for example passing invalid options to macros will crash the program and getting better feedback fast is also a plus for me.
In general I (try to) run a tight ship, more so than most Elixir Gurus from what I can tell.