Он работает следующим образом. Посмотрите исходный код ExUnit.Case.
Вначале посмотрите на макрос __using__
, так как он будет вызываться первым, когда вы используете его в тестовом примере. В частности, обратите внимание here
Enum.each [:ex_unit_tests, :tag, :describetag, :moduletag, :ex_unit_registered],
&Module.register_attribute(__MODULE__, &1, accumulate: true)
Это регистрирует @tag
и кучу более атрибутов, как накапливается. Прочитайте документы Module.register_attribute/3, и вы увидите, что это означает, что вызывается атрибут anytime, значение добавляется к списку предыдущих атрибутов.
Затем обратите внимание test/3
макрос, в частности here
quote bind_quoted: [var: var, contents: contents, message: message] do
name = ExUnit.Case.register_test(__ENV__, :test, message, [])
def unquote(name)(unquote(var)), do: unquote(contents)
end
Примечание вызов ExUnit.Case.register_test/4
. Глядя на него, специально here
tag = Module.delete_attribute(mod, :tag)
Он извлекает теги, пока здесь, и удаляет их. И при наличии метки, и название теста, он вызывает (here)
test = %ExUnit.Test{name: name, case: mod, tags: tags}
Module.put_attribute(mod, :ex_unit_tests, test)
который сохраняет тест вместе с тегами внутри другой атрибутов.
И наконец, обратите внимание, здесь
@doc false
defmacro __before_compile__(_) do
quote do
def __ex_unit__(:case) do
%ExUnit.TestCase{name: __MODULE__, tests: @ex_unit_tests}
end
end
end
Функция __ex_unit__/1
вызывается в ExUnit.Runner.run_case/3, чтобы получить информацию о тестах внутри каждого конкретного случая.
Вы видите точку? Используйте накопленный атрибут, внутри вашего макроса вызывается функция, которая всегда получает текущее значение атрибута и очищает его, а затем делает все, что угодно, со значением, потому что вы знаете, что это всегда, когда вызывается макрос.
Я надеюсь, что было достаточно ясно, напишите комментарий, если вам нужно больше объяснений.
PS. Я просто прочитал исходный код, чтобы узнать это. Было интересно узнать, как это работает.
Вы просматриваете эту страницу? http://elixir-lang.org/docs/master/ex_unit/ExUnit.Case.html Более конкретно этот раздел этой страницы имеет отношение к вашему вопросу: http://elixir-lang.org/docs/master/ex_unit/ ExUnit.Case.html # module-tags Есть ли что-то на этой странице, что вам непонятно? Ваш вопрос мне не очень понятен. –
Я не знаю, что вы показываете, мне да ExUnit имеет @tags, которые действуют как аннотации к функциям, мой вопрос в том, как они это достигли.Я на самом деле решаю, как он возится с вещами, и теперь у меня есть еще одна проблема, которая действительно могла сделать что-нибудь полезное с этими аннотациями во время компиляции. Здесь моя зарплата: https://github.com/chrisjowen/annotatable – Owen
Хорошо, тогда возьмите мой комментарий как знак того, что не совсем понятно, что вы хотите знать. –