summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@dashbit.co>2022-11-03 11:50:09 +0100
committerJosé Valim <jose.valim@dashbit.co>2022-11-03 11:56:44 +0100
commitc01658b12d1add1de17df70724f4e6f90c61c093 (patch)
tree513e8a97d7b55dc3c10312684776d746de97cd01
parentfdf96ad48a42d2859ac3cf9e083a3ec29e412b4a (diff)
downloadelixir-c01658b12d1add1de17df70724f4e6f90c61c093.tar.gz
Add doctest metadata as tags
-rw-r--r--lib/ex_unit/lib/ex_unit/case.ex22
-rw-r--r--lib/ex_unit/lib/ex_unit/doc_test.ex47
-rw-r--r--lib/ex_unit/lib/ex_unit/runner.ex2
-rw-r--r--lib/ex_unit/test/ex_unit/doc_test_test.exs18
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