diff options
author | José Valim <jose.valim@dashbit.co> | 2022-11-03 11:50:09 +0100 |
---|---|---|
committer | José Valim <jose.valim@dashbit.co> | 2022-11-03 11:56:44 +0100 |
commit | c01658b12d1add1de17df70724f4e6f90c61c093 (patch) | |
tree | 513e8a97d7b55dc3c10312684776d746de97cd01 | |
parent | fdf96ad48a42d2859ac3cf9e083a3ec29e412b4a (diff) | |
download | elixir-c01658b12d1add1de17df70724f4e6f90c61c093.tar.gz |
Add doctest metadata as tags
-rw-r--r-- | lib/ex_unit/lib/ex_unit/case.ex | 22 | ||||
-rw-r--r-- | lib/ex_unit/lib/ex_unit/doc_test.ex | 47 | ||||
-rw-r--r-- | lib/ex_unit/lib/ex_unit/runner.ex | 2 | ||||
-rw-r--r-- | lib/ex_unit/test/ex_unit/doc_test_test.exs | 18 |
4 files changed, 49 insertions, 40 deletions
diff --git a/lib/ex_unit/lib/ex_unit/case.ex b/lib/ex_unit/lib/ex_unit/case.ex index 6d25e5262..503549a83 100644 --- a/lib/ex_unit/lib/ex_unit/case.ex +++ b/lib/ex_unit/lib/ex_unit/case.ex @@ -156,6 +156,10 @@ defmodule ExUnit.Case do * `:describe_line` - the line the describe block begins on + * `:doctest` - the module or the file being doctested (if a doctest) + + * `:doctest_line` - the line the doctest was defined (if a doctest) + The following tags customize how tests behave: * `:capture_log` - see the "Log Capture" section below @@ -167,8 +171,8 @@ defmodule ExUnit.Case do * `:tmp_dir` - (since v1.11.0) see the "Tmp Dir" section below - The `:test_type` tag is automatically set by ExUnit, but is **not** reserved. - This tag is available for users to customize if they desire. + * `:test_type` - the test type used when printing test results. + It is set by ExUnit to `:test`, `:doctest` and so on, but is customizable. ## Filters @@ -476,10 +480,16 @@ defmodule ExUnit.Case do end @doc false - defmacro __before_compile__(_) do + defmacro __before_compile__(env) do + tests = + env.module + |> Module.get_attribute(:ex_unit_tests) + |> Enum.reverse() + |> Macro.escape() + quote do def __ex_unit__ do - %ExUnit.TestModule{file: __ENV__.file, name: __MODULE__, tests: @ex_unit_tests} + %ExUnit.TestModule{file: __ENV__.file, name: __MODULE__, tests: unquote(tests)} end end end @@ -581,6 +591,7 @@ defmodule ExUnit.Case do This function is deprecated in favor of `register_test/6` which performs better under tight loops by avoiding `__ENV__`. """ + # TODO: Deprecate on Elixir v1.17 @doc deprecated: "Use register_test/6 instead" def register_test(%{module: mod, file: file, line: line}, test_type, name, tags) do register_test(mod, file, line, test_type, name, tags) @@ -758,8 +769,9 @@ defmodule ExUnit.Case do defp normalize_tags(tags) do Enum.reduce(Enum.reverse(tags), %{}, fn + {key, value}, acc -> Map.put(acc, key, value) tag, acc when is_atom(tag) -> Map.put(acc, tag, true) - tag, acc when is_list(tag) -> tag |> Enum.into(acc) + tag, acc when is_list(tag) -> Enum.into(tag, acc) end) end end diff --git a/lib/ex_unit/lib/ex_unit/doc_test.ex b/lib/ex_unit/lib/ex_unit/doc_test.ex index 83d900245..bc4df8a9b 100644 --- a/lib/ex_unit/lib/ex_unit/doc_test.ex +++ b/lib/ex_unit/lib/ex_unit/doc_test.ex @@ -193,25 +193,27 @@ defmodule ExUnit.DocTest do This macro is auto-imported with every `ExUnit.Case`. """ defmacro doctest(module, opts \\ []) do + caller = __CALLER__ + require = - if is_atom(Macro.expand(module, __CALLER__)) do + if is_atom(Macro.expand(module, caller)) do quote do require unquote(module) end end tests = - quote bind_quoted: [module: module, opts: opts] do - env = __ENV__ + quote bind_quoted: [ + module: module, + opts: opts, + env_line: caller.line, + env_file: caller.file + ] do file = ExUnit.DocTest.__file__(module) - for {name, test} <- ExUnit.DocTest.__doctests__(module, opts) do - if tags = Keyword.get(opts, :tags) do - @tag tags - end - + for {name, test, tags} <- ExUnit.DocTest.__doctests__(module, opts) do @file file - doc = ExUnit.Case.register_test(env, :doctest, name, []) + doc = ExUnit.Case.register_test(__MODULE__, env_file, env_line, :doctest, name, tags) def unquote(doc)(_), do: unquote(test) end end @@ -230,13 +232,15 @@ defmodule ExUnit.DocTest do @doc false def __doctests__(module, opts) do - do_import = Keyword.get(opts, :import, false) + tags = [doctest: module] ++ Keyword.get(opts, :tags, []) + import = Keyword.get(opts, :import, false) + file = module.module_info(:compile)[:source] |> Path.relative_to_cwd() extract(module) |> filter_by_opts(module, opts) - |> Stream.with_index() + |> Stream.with_index(1) |> Enum.map(fn {test, acc} -> - compile_test(test, module, do_import, acc + 1) + compile_test(test, module, import, acc, file, tags) end) end @@ -244,14 +248,9 @@ defmodule ExUnit.DocTest do except = Keyword.get(opts, :except, []) case Keyword.fetch(opts, :only) do - {:ok, []} -> - [] - - {:ok, only} -> - filter_tests(module, tests, except, only) - - :error -> - Stream.reject(tests, &(&1.fun_arity in except)) + {:ok, []} -> [] + {:ok, only} -> filter_tests(module, tests, except, only) + :error -> Stream.reject(tests, &(&1.fun_arity in except)) end end @@ -287,8 +286,9 @@ defmodule ExUnit.DocTest do ## Compilation of extracted tests - defp compile_test(test, module, do_import, n) do - {test_name(test, module, n), test_content(test, module, do_import)} + defp compile_test(test, module, do_import, n, file, tags) do + tags = [doctest_line: test.line] ++ tags + {test_name(test, module, n), test_content(test, module, do_import, file), tags} end defp test_name(%{fun_arity: :moduledoc}, m, n) do @@ -299,8 +299,7 @@ defmodule ExUnit.DocTest do "#{inspect(m)}.#{f}/#{a} (#{n})" end - defp test_content(%{exprs: exprs, line: line}, module, do_import) do - file = module.module_info(:compile)[:source] |> Path.relative_to_cwd() + defp test_content(%{exprs: exprs, line: line}, module, do_import, file) do location = [line: line, file: file] stack = Macro.escape([{module, :__MODULE__, 0, location}]) diff --git a/lib/ex_unit/lib/ex_unit/runner.ex b/lib/ex_unit/lib/ex_unit/runner.ex index ab6290c07..5c901044b 100644 --- a/lib/ex_unit/lib/ex_unit/runner.ex +++ b/lib/ex_unit/lib/ex_unit/runner.ex @@ -571,7 +571,7 @@ defmodule ExUnit.Runner do end defp shuffle(%{seed: 0}, list) do - Enum.reverse(list) + list end defp shuffle(%{seed: seed}, list) do diff --git a/lib/ex_unit/test/ex_unit/doc_test_test.exs b/lib/ex_unit/test/ex_unit/doc_test_test.exs index 704bca7d7..e9be1e2b0 100644 --- a/lib/ex_unit/test/ex_unit/doc_test_test.exs +++ b/lib/ex_unit/test/ex_unit/doc_test_test.exs @@ -865,18 +865,16 @@ defmodule ExUnit.DocTestTest do end end - test "doctests type" do - defmodule DoctestType do - use ExUnit.Case - doctest ExUnit.DocTestTest.NoImport - - setup test do - assert test.test_type == :doctest - :ok - end + test "doctests built-in tags" do + alias ExUnit.DocTestTest.NoImport + defmodule DoctestTags do + use ExUnit.Case, register: false + doctest NoImport end - assert capture_io(fn -> ExUnit.run() end) =~ "2 doctests, 0 failures" + assert %ExUnit.TestModule{tests: [test1, test2]} = DoctestTags.__ex_unit__() + assert %{test_type: :doctest, doctest: NoImport, doctest_line: 129} = test1.tags + assert %{test_type: :doctest, doctest: NoImport, doctest_line: 132} = test2.tags end test "multiple exceptions in one test case is not supported" do |