このように動作します。ソースコードExUnit.Caseを見てください。
最初に、__using__
マクロを調べます。これは、テストケースで使用するときに最初に呼び出されるためです。特に、これは@tag
と蓄積されたとして、より多くの属性の束を登録here
Enum.each [:ex_unit_tests, :tag, :describetag, :moduletag, :ex_unit_registered],
&Module.register_attribute(__MODULE__, &1, accumulate: true)
に注意してください。 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
あなたが知りたいことがきわめて明確ではないことを看板として私のコメントをしてください。 –