Skip to content

Commit fc5050d

Browse files
author
José Valim
committed
Convert ex_unit context to a map
1 parent 011ad07 commit fc5050d

File tree

6 files changed

+55
-47
lines changed

6 files changed

+55
-47
lines changed

lib/ex_unit/lib/ex_unit/callbacks.ex

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ defmodule ExUnit.Callbacks do
55
This module defines four callbacks: `setup_all`, `teardown_all`,
66
`setup` and `teardown`.
77
8-
These callbacks are defined via macros and each one can optionally receive a
9-
keyword list with metadata, usually referred to as `context`. The callback
8+
These callbacks are defined via macros and each one can optionally receive
9+
a map with metadata, usually referred to as `context`. The callback
1010
may optionally put extra data into `context` to be used in the tests.
1111
12-
If you return `{:ok, <keyword list>}` from `setup` or `teardown`, the keyword
12+
If you return `{:ok, <dict>}` from `setup` or `teardown`, the keyword
1313
list will be merged into the context that will be available in all
1414
subsequent `setup`, `test` or `teardown` calls.
1515
16-
Similarly, returning `{:ok, <keyword list>}` from `setup_all` or
16+
Similarly, returning `{:ok, <dict>}` from `setup_all` or
1717
`teardown_all` will merge the keyword list into the context that will be
1818
available in all subsequent `setup_all` or `teardown_all` calls.
1919
@@ -41,8 +41,8 @@ defmodule ExUnit.Callbacks do
4141
setup do
4242
IO.puts "This is a setup callback"
4343
44-
# Return extra metadata, it must be a keyword list
45-
{:ok, [hello: "world"]}
44+
# Return extra metadata, it must be a keyword list / map
45+
{:ok, hello: "world"}
4646
end
4747
4848
# Same as `setup`, but receives the context for the current test
@@ -89,10 +89,10 @@ defmodule ExUnit.Callbacks do
8989

9090
@doc false
9191
defmacro __before_compile__(env) do
92-
[ compile_callbacks(env, :setup),
93-
compile_callbacks(env, :teardown),
94-
compile_callbacks(env, :setup_all),
95-
compile_callbacks(env, :teardown_all) ]
92+
[compile_callbacks(env, :setup),
93+
compile_callbacks(env, :teardown),
94+
compile_callbacks(env, :setup_all),
95+
compile_callbacks(env, :teardown_all)]
9696
end
9797

9898
@doc """
@@ -150,13 +150,13 @@ defmodule ExUnit.Callbacks do
150150
{:ok, other}
151151
end
152152

153-
def __merge__(_mod, other, {:ok, data}) when is_list(data) do
154-
{:ok, Keyword.merge(other, data)}
153+
def __merge__(_mod, other, {:ok, data}) do
154+
{:ok, Dict.merge(other, data)}
155155
end
156156

157157
def __merge__(mod, _, failure) do
158158
raise "expected ExUnit callback in #{inspect mod} to return :ok " <>
159-
" or {:ok, keywords}, got #{inspect failure} instead"
159+
" or {:ok, dict}, got #{inspect failure} instead"
160160
end
161161

162162
defp escape(contents) do

lib/ex_unit/lib/ex_unit/case.ex

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ defmodule ExUnit.Case do
4646
end
4747
end
4848
49+
As the context is a map, it can be pattern matched on to extract
50+
information:
51+
52+
test "stores key-values", %{pid: pid} do
53+
assert KV.put(pid, :hello, :world) == :ok
54+
assert KV.get(pid, :hello) == :world
55+
end
56+
4957
## Tags
5058
5159
The context is used to pass information from the callbacks to
@@ -234,7 +242,7 @@ defmodule ExUnit.Case do
234242
def __on_definition__(env, name) do
235243
mod = env.module
236244
tags = Module.get_attribute(mod, :tag) ++ Module.get_attribute(mod, :moduletag)
237-
tags = [line: env.line, file: env.file] ++ normalize_tags(tags)
245+
tags = tags |> normalize_tags |> Map.merge(%{line: env.line, file: env.file})
238246

239247
Module.put_attribute(mod, :ex_unit_tests,
240248
%ExUnit.Test{name: name, case: mod, tags: tags})
@@ -243,9 +251,9 @@ defmodule ExUnit.Case do
243251
end
244252

245253
defp normalize_tags(tags) do
246-
Enum.reduce tags, [], fn
247-
tag, acc when is_atom(tag) -> Keyword.put_new(acc, tag, true)
248-
tag, acc when is_list(tag) -> Keyword.merge(tag, acc)
254+
Enum.reduce Enum.reverse(tags), %{}, fn
255+
tag, acc when is_atom(tag) -> Map.put(acc, tag, true)
256+
tag, acc when is_list(tag) -> Dict.merge(acc, tag)
249257
end
250258
end
251259
end

lib/ex_unit/lib/ex_unit/filters.ex

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,15 @@ defmodule ExUnit.Filters do
6969
7070
## Examples
7171
72-
iex> ExUnit.Filters.eval([foo: "bar"], [:foo], [foo: "bar"])
72+
iex> ExUnit.Filters.eval([foo: "bar"], [:foo], %{foo: "bar"})
7373
:ok
7474
75-
iex> ExUnit.Filters.eval([foo: "bar"], [:foo], [foo: "baz"])
75+
iex> ExUnit.Filters.eval([foo: "bar"], [:foo], %{foo: "baz"})
7676
{:error, :foo}
7777
7878
"""
79-
@spec eval(t, t, Keyword.t) :: :ok | {:error, atom}
80-
def eval(include, exclude, tags) do
79+
@spec eval(t, t, map) :: :ok | {:error, atom}
80+
def eval(include, exclude, tags) when is_map(tags) do
8181
excluded = Enum.find_value exclude, &has_tag(&1, tags)
8282
if !excluded or Enum.any?(include, &has_tag(&1, tags)) do
8383
:ok
@@ -87,22 +87,22 @@ defmodule ExUnit.Filters do
8787
end
8888

8989
defp has_tag({key, %Regex{} = value}, tags) when is_atom(key) do
90-
case Keyword.fetch(tags, key) do
90+
case Map.fetch(tags, key) do
9191
{:ok, tag} -> to_string(tag) =~ value and key
9292
_ -> false
9393
end
9494
end
9595

9696
defp has_tag({key, value}, tags) when is_atom(key) do
97-
case Keyword.fetch(tags, key) do
97+
case Map.fetch(tags, key) do
9898
{:ok, ^value} -> key
9999
{:ok, tag} -> compare(to_string(tag), to_string(value)) and key
100100
_ -> false
101101
end
102102
end
103103

104104
defp has_tag(key, tags) when is_atom(key),
105-
do: Keyword.has_key?(tags, key) and key
105+
do: Map.has_key?(tags, key) and key
106106

107107
defp compare("Elixir." <> tag, tag), do: true
108108
defp compare(tag, tag), do: true

lib/ex_unit/lib/ex_unit/runner.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ defmodule ExUnit.Runner do
129129
exclude = config.exclude
130130

131131
for test <- tests do
132-
tags = Keyword.put(test.tags, :test, test.name)
132+
tags = Map.put(test.tags, :test, test.name)
133133
case ExUnit.Filters.eval(include, exclude, tags) do
134134
:ok -> %{test | tags: tags}
135135
{:error, tag} -> %{test | state: {:skip, "due to #{tag} filter"}}
@@ -163,7 +163,7 @@ defmodule ExUnit.Runner do
163163
end
164164

165165
defp exec_case_setup(%ExUnit.TestCase{name: case_name} = test_case) do
166-
{:ok, context} = case_name.__ex_unit__(:setup_all, [case: case_name])
166+
{:ok, context} = case_name.__ex_unit__(:setup_all, %{case: case_name})
167167
{:ok, {test_case, context}}
168168
catch
169169
kind, error ->
@@ -184,7 +184,7 @@ defmodule ExUnit.Runner do
184184
EM.test_started(config.manager, test)
185185

186186
if nil?(test.state) do
187-
test = spawn_test(config, test, Keyword.merge(test.tags, context))
187+
test = spawn_test(config, test, Map.merge(test.tags, context))
188188
end
189189

190190
EM.test_finished(config.manager, test)

lib/ex_unit/test/ex_unit/case_template_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ defmodule ExUnit.CaseTemplateTest do
5555
assert 2 == unquote(two)
5656
end
5757

58-
test "receives context from parent case", context do
59-
assert context[:context] == :setup
58+
test "receives context from parent case", %{context: context} do
59+
assert context == :setup
6060
end
6161

6262
test "runs both templates setup", context do

lib/ex_unit/test/ex_unit/filters_test.exs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,35 @@ defmodule ExUnit.FiltersTest do
66
doctest ExUnit.Filters
77

88
test "evaluating filters" do
9-
assert ExUnit.Filters.eval([], [:os], []) == :ok
10-
assert ExUnit.Filters.eval([], [os: :win], [os: :unix]) == :ok
11-
assert ExUnit.Filters.eval([], [:os], [os: :unix]) == {:error, :os}
12-
assert ExUnit.Filters.eval([], [os: :unix], [os: :unix]) == {:error, :os}
9+
assert ExUnit.Filters.eval([], [:os], %{}) == :ok
10+
assert ExUnit.Filters.eval([], [os: :win], %{os: :unix}) == :ok
11+
assert ExUnit.Filters.eval([], [:os], %{os: :unix}) == {:error, :os}
12+
assert ExUnit.Filters.eval([], [os: :unix], %{os: :unix}) == {:error, :os}
1313

14-
assert ExUnit.Filters.eval([os: :win], [], []) == :ok
15-
assert ExUnit.Filters.eval([os: :win], [], [os: :unix]) == :ok
16-
assert ExUnit.Filters.eval([os: :win], [:os], []) == :ok
17-
assert ExUnit.Filters.eval([os: :win], [:os], [os: :win]) == :ok
14+
assert ExUnit.Filters.eval([os: :win], [], %{}) == :ok
15+
assert ExUnit.Filters.eval([os: :win], [], %{os: :unix}) == :ok
16+
assert ExUnit.Filters.eval([os: :win], [:os], %{}) == :ok
17+
assert ExUnit.Filters.eval([os: :win], [:os], %{os: :win}) == :ok
1818

19-
assert ExUnit.Filters.eval([os: :win, os: :unix], [:os], [os: :win]) == :ok
19+
assert ExUnit.Filters.eval([os: :win, os: :unix], [:os], %{os: :win}) == :ok
2020
end
2121

2222
test "evaluating filters matches integers" do
23-
assert ExUnit.Filters.eval([line: "1"], [], [line: 1]) == :ok
24-
assert ExUnit.Filters.eval([line: "1"], [line: 5], [line: 1]) == :ok
25-
assert ExUnit.Filters.eval([line: "1"], [:line], [line: 1]) == :ok
23+
assert ExUnit.Filters.eval([line: "1"], [], %{line: 1}) == :ok
24+
assert ExUnit.Filters.eval([line: "1"], [line: 5], %{line: 1}) == :ok
25+
assert ExUnit.Filters.eval([line: "1"], [:line], %{line: 1}) == :ok
2626
end
2727

2828
test "evaluating filter matches atoms" do
29-
assert ExUnit.Filters.eval([os: "win"], [], [os: :win]) == :ok
30-
assert ExUnit.Filters.eval([os: "win"], [os: :unix], [os: :win]) == :ok
31-
assert ExUnit.Filters.eval([os: "win"], [:os], [os: :win]) == :ok
32-
assert ExUnit.Filters.eval([case: "Foo"], [:os], [case: Foo]) == :ok
29+
assert ExUnit.Filters.eval([os: "win"], [], %{os: :win}) == :ok
30+
assert ExUnit.Filters.eval([os: "win"], [os: :unix], %{os: :win}) == :ok
31+
assert ExUnit.Filters.eval([os: "win"], [:os], %{os: :win}) == :ok
32+
assert ExUnit.Filters.eval([case: "Foo"], [:os], %{case: Foo}) == :ok
3333
end
3434

3535
test "evaluating filter matches regexes" do
36-
assert ExUnit.Filters.eval([os: ~r"win"], [], [os: :win]) == :ok
37-
assert ExUnit.Filters.eval([os: ~r"mac"], [os: :unix], [os: :unix]) == {:error, :os}
36+
assert ExUnit.Filters.eval([os: ~r"win"], [], %{os: :win}) == :ok
37+
assert ExUnit.Filters.eval([os: ~r"mac"], [os: :unix], %{os: :unix}) == {:error, :os}
3838
end
3939

4040
test "parsing filters" do

0 commit comments

Comments
 (0)