Skip to content

Commit f2ab40b

Browse files
authored
Expose compile-time test and tag information (#12608)
1 parent 3b77086 commit f2ab40b

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

lib/ex_unit/lib/ex_unit/case.ex

+21
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,27 @@ defmodule ExUnit.Case do
765765
end
766766
end
767767

768+
@doc """
769+
Returns the most recently registered test case as an `%ExUnit.Test{}`
770+
struct.
771+
772+
This is used by third-party utilities to allow compile-time configuration
773+
using test tags without having to explicitly pass the test context at
774+
run-time. It is intended to be invoked in macros before the test module
775+
is compiled.
776+
777+
Raises if called with a module that has already been compiled.
778+
"""
779+
@doc since: "1.15.0"
780+
@spec get_last_registered_test(env) :: ExUnit.Test.t() | nil
781+
def get_last_registered_test(%{module: mod}) do
782+
get_last_registered_test(mod)
783+
end
784+
785+
def get_last_registered_test(mod) when is_atom(mod) do
786+
Module.get_last_attribute(mod, :ex_unit_tests)
787+
end
788+
768789
defp validate_tags(tags) do
769790
for tag <- @reserved, Map.has_key?(tags, tag) do
770791
raise "cannot set tag #{inspect(tag)} because it is reserved by ExUnit"

lib/ex_unit/test/ex_unit/case_test.exs

+52
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,55 @@ defmodule ExUnit.BadOptsCase do
262262
end
263263
end
264264
end
265+
266+
defmodule ExUnit.CaseTest.GetLastRegisteredTestHelper do
267+
defmacro escaped_get_last_registered_test do
268+
Macro.escape(ExUnit.Case.get_last_registered_test(__CALLER__))
269+
end
270+
end
271+
272+
defmodule ExUnit.CaseTest.GetLastRegisteredTestTest do
273+
use ExUnit.Case, async: true
274+
import ExUnit.CaseTest.GetLastRegisteredTestHelper
275+
276+
last = ExUnit.Case.get_last_registered_test(__MODULE__)
277+
278+
test "returns nil if called before any test has been registered" do
279+
assert unquote(last) == nil
280+
end
281+
282+
test "returns the current test if call is within test body", %{test: name} do
283+
assert %ExUnit.Test{
284+
name: ^name,
285+
module: __MODULE__,
286+
state: nil,
287+
time: 0
288+
} = escaped_get_last_registered_test()
289+
end
290+
291+
last = ExUnit.Case.get_last_registered_test(__MODULE__)
292+
293+
test "returns the previous test if call is outside test body" do
294+
assert %ExUnit.Test{name: :"test returns the current test if call is within test body"} =
295+
unquote(Macro.escape(last))
296+
end
297+
298+
test "raises if given module is already compiled" do
299+
assert_raise ArgumentError, ~r/could not call Module\.get_last_attribute\/2/, fn ->
300+
ExUnit.Case.get_last_registered_test(__MODULE__)
301+
end
302+
end
303+
304+
@moduletag tag1: :foo
305+
describe "tags" do
306+
@describetag tag2: :bar
307+
308+
@tag tag3: :baz
309+
test "includes data available in test context", context do
310+
assert %ExUnit.Test{tags: %{tag1: :foo, tag2: :bar, tag3: :baz} = tags} =
311+
escaped_get_last_registered_test()
312+
313+
assert tags == Map.take(context, Map.keys(tags))
314+
end
315+
end
316+
end

0 commit comments

Comments
 (0)