Skip to content

Commit 5bab9ca

Browse files
author
José Valim
committed
Avoid race conditions on ExUnit test suite
1 parent 05507d1 commit 5bab9ca

File tree

6 files changed

+107
-159
lines changed

6 files changed

+107
-159
lines changed
Lines changed: 73 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,42 @@
11
Code.require_file "../test_helper.exs", __DIR__
22

33
defmodule ExUnit.CallbacksTest do
4-
use ExUnit.Case, async: true
5-
6-
setup_all do
7-
{:ok, [context: :setup_all]}
8-
end
9-
10-
setup do
11-
{:ok, [initial_setup: true]}
12-
end
13-
14-
setup context do
15-
assert context[:initial_setup]
16-
assert context[:context] == :setup_all
17-
{:ok, [context: :setup]}
18-
end
19-
20-
setup context do
21-
if Process.get(:ex_unit_callback) do
22-
raise "ex_unit_callback was not cleaned"
23-
else
24-
Process.put(:ex_unit_callback, context[:test])
25-
end
26-
:ok
27-
end
28-
29-
teardown context do
30-
assert context[:context] == :setup
31-
{:ok, context: :teardown}
32-
end
33-
34-
teardown context do
35-
assert Process.get(:ex_unit_callback) == context[:test]
36-
Process.delete(:ex_unit_callback)
37-
assert context[:context] == :teardown
38-
:ok
39-
end
40-
41-
teardown_all context do
42-
assert context[:context] == :setup_all
43-
:ok
44-
end
4+
use ExUnit.Case
455

466
import ExUnit.CaptureIO
477

48-
test "callbacks can run custom code" do
49-
assert Process.get(:ex_unit_callback) == :"test callbacks can run custom code"
50-
end
51-
52-
test "receives context from callback", context do
53-
assert context[:context] == :setup
54-
end
55-
56-
test "doesn't choke on setup errors" do
57-
defmodule SetupTest do
8+
test "callbacks run custom code with context" do
9+
defmodule CallbacksTest do
5810
use ExUnit.Case
5911

60-
setup _ do
61-
:ok = error
12+
setup_all do
13+
{:ok, [context: :setup_all]}
6214
end
6315

64-
test "ok" do
65-
:ok
16+
setup do
17+
{:ok, [initial_setup: true]}
6618
end
6719

68-
defp error, do: :error
69-
end
70-
71-
assert capture_io(fn -> ExUnit.run end) =~
72-
"** (MatchError) no match of right hand side value: :error"
73-
end
74-
75-
test "doesn't choke on setup_all errors" do
76-
defmodule SetupAllTest do
77-
use ExUnit.Case, async: false
78-
79-
setup_all _ do
80-
:ok = error
20+
setup context do
21+
assert context[:initial_setup]
22+
assert context[:context] == :setup_all
23+
{:ok, [context: :setup]}
8124
end
8225

83-
test "ok" do
84-
:ok
26+
test "callbacks", context do
27+
assert context[:context] == :setup
8528
end
86-
87-
defp error, do: :error
8829
end
8930

90-
ExUnit.configure(formatters: [ExUnit.CLIFormatter])
91-
9231
assert capture_io(fn -> ExUnit.run end) =~
93-
"** (MatchError) no match of right hand side value: :error"
32+
"1 tests, 0 failures"
9433
end
9534

96-
test "doesn't choke on teardown errors" do
97-
defmodule TeardownTest do
98-
use ExUnit.Case, async: false
35+
test "doesn't choke on setup errors" do
36+
defmodule SetupTest do
37+
use ExUnit.Case
9938

100-
teardown _ do
39+
setup _ do
10140
:ok = error
10241
end
10342

@@ -112,11 +51,11 @@ defmodule ExUnit.CallbacksTest do
11251
"** (MatchError) no match of right hand side value: :error"
11352
end
11453

115-
test "doesn't choke on teardown_all errors" do
116-
defmodule TeardownAllTest do
54+
test "doesn't choke on setup_all errors" do
55+
defmodule SetupAllTest do
11756
use ExUnit.Case, async: false
11857

119-
teardown_all _ do
58+
setup_all _ do
12059
:ok = error
12160
end
12261

@@ -136,18 +75,13 @@ defmodule ExUnit.CallbacksTest do
13675
use ExUnit.Case, async: false
13776

13877
test "ok" do
139-
on_exit fn ->
140-
:ok = error
141-
end
142-
78+
on_exit fn -> :ok = error end
14379
:ok
14480
end
14581

14682
defp error, do: :error
14783
end
14884

149-
ExUnit.configure(formatters: [ExUnit.CLIFormatter])
150-
15185
assert capture_io(fn -> ExUnit.run end) =~
15286
"** (MatchError) no match of right hand side value: :error"
15387
end
@@ -157,21 +91,22 @@ defmodule ExUnit.CallbacksTest do
15791
use ExUnit.Case, async: false
15892

15993
test "ok" do
160-
on_exit fn ->
161-
Process.exit(self(), :kill)
162-
end
163-
94+
on_exit fn -> Process.exit(self(), :kill) end
16495
:ok
16596
end
16697
end
16798

168-
ExUnit.configure(formatters: [ExUnit.CLIFormatter])
16999
assert capture_io(fn -> ExUnit.run end) =~
170100
">) killed"
171101
end
172102

103+
defp no_formatters! do
104+
ExUnit.configure(formatters: [])
105+
on_exit fn -> ExUnit.configure(formatters: [ExUnit.CLIFormatter]) end
106+
end
107+
173108
test "runs multiple on_exit exits and overrides by ref" do
174-
defmodule OnExitOverrideTest do
109+
defmodule OnExitSuccessTest do
175110
use ExUnit.Case, async: false
176111

177112
setup do
@@ -182,12 +117,16 @@ defmodule ExUnit.CallbacksTest do
182117
on_exit {:overridden, 1}, fn ->
183118
IO.puts "on_exit 1 overridden -> not run"
184119
end
120+
121+
:ok
185122
end
186123

187124
setup_all do
188125
on_exit fn ->
189126
IO.puts "on_exit setup_all run"
190127
end
128+
129+
:ok
191130
end
192131

193132
test "ok" do
@@ -211,7 +150,7 @@ defmodule ExUnit.CallbacksTest do
211150
end
212151
end
213152

214-
ExUnit.configure(formatters: [ExUnit.CLIFormatter])
153+
no_formatters!
215154
output = capture_io(fn -> ExUnit.run end)
216155

217156
assert output =~ """
@@ -224,6 +163,45 @@ defmodule ExUnit.CallbacksTest do
224163

225164
refute output =~ "not run"
226165
end
166+
167+
test "runs multiple on_exit on failure" do
168+
defmodule OnExitFailureTest do
169+
use ExUnit.Case, async: false
170+
171+
setup do
172+
on_exit fn ->
173+
IO.puts "on_exit setup run"
174+
end
175+
176+
:ok
177+
end
178+
179+
setup_all do
180+
on_exit fn ->
181+
IO.puts "on_exit setup_all run"
182+
end
183+
184+
:ok
185+
end
186+
187+
test "ok" do
188+
on_exit fn ->
189+
IO.puts "simple on_exit run"
190+
end
191+
192+
flunk "oops"
193+
end
194+
end
195+
196+
no_formatters!
197+
output = capture_io(fn -> ExUnit.run end)
198+
199+
assert output =~ """
200+
simple on_exit run
201+
on_exit setup run
202+
on_exit setup_all run
203+
"""
204+
end
227205
end
228206

229207
defmodule ExUnit.CallbacksNoTests do
@@ -236,12 +214,4 @@ defmodule ExUnit.CallbacksNoTests do
236214
setup do
237215
raise "Never run"
238216
end
239-
240-
teardown do
241-
raise "Never run"
242-
end
243-
244-
teardown_all do
245-
raise "Never run"
246-
end
247217
end

lib/ex_unit/test/ex_unit/capture_io_test.exs

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,32 @@
11
Code.require_file "../test_helper.exs", __DIR__
22

3-
defmodule ExUnit.CaptureIOTest.Value do
4-
def binary, do: "a"
5-
end
6-
7-
alias ExUnit.CaptureIOTest.Value
3+
defmodule ExUnit.CaptureIOTest do
4+
use ExUnit.Case
85

9-
defmodule ExUnit.CaptureIOTest.GetUntil do
10-
def until_new_line(_, :eof, _) do
11-
{:done, :eof, []}
12-
end
6+
defmodule GetUntil do
7+
def until_new_line(_, :eof, _) do
8+
{:done, :eof, []}
9+
end
1310

14-
def until_new_line(this_far, chars, stop_char) do
15-
case Enum.split_while(chars, fn(c) -> c != stop_char end) do
16-
{l, []} ->
17-
{:more, this_far ++ l}
18-
{l, [stop_char|rest]} ->
19-
{:done, this_far ++ l ++ [stop_char], rest}
11+
def until_new_line(this_far, chars, stop_char) do
12+
case Enum.split_while(chars, fn(c) -> c != stop_char end) do
13+
{l, []} ->
14+
{:more, this_far ++ l}
15+
{l, [stop_char|rest]} ->
16+
{:done, this_far ++ l ++ [stop_char], rest}
17+
end
2018
end
21-
end
2219

23-
def get_line(device \\ Process.group_leader) do
24-
send device, {:io_request, self, device, {:get_until, :unicode, "", __MODULE__, :until_new_line, [?\n]}}
25-
receive do
26-
{:io_reply, _, data} -> data
20+
def get_line(device \\ Process.group_leader) do
21+
send device, {:io_request, self, device, {:get_until, :unicode, "", __MODULE__, :until_new_line, [?\n]}}
22+
receive do
23+
{:io_reply, _, data} -> data
24+
end
2725
end
2826
end
29-
end
30-
31-
alias ExUnit.CaptureIOTest.GetUntil
32-
33-
defmodule ExUnit.CaptureIOTest do
34-
use ExUnit.Case
35-
36-
doctest ExUnit.CaptureIO, import: true
3727

3828
import ExUnit.CaptureIO
29+
doctest ExUnit.CaptureIO, import: true
3930

4031
test "with no output" do
4132
assert capture_io(fn ->
@@ -52,10 +43,6 @@ defmodule ExUnit.CaptureIOTest do
5243
:io.put_chars("b")
5344
end) == "ab"
5445

55-
assert capture_io(fn ->
56-
send_and_receive_io({:put_chars, :unicode, Value, :binary, []})
57-
end) == "a"
58-
5946
assert capture_io(fn ->
6047
:io.put_chars("josé")
6148
end) == "josé"

lib/ex_unit/test/ex_unit/case_template_test.exs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,6 @@ defmodule ExUnit.SampleCase do
2121
assert context[:context] == :setup_all
2222
{:ok, [context: :setup, setup: 1]}
2323
end
24-
25-
teardown context do
26-
assert context[:context] == :setup
27-
:ok
28-
end
29-
30-
teardown_all context do
31-
assert context[:context] == :setup_all
32-
:ok
33-
end
3424
end
3525

3626
defmodule ExUnit.NestedCase do

lib/ex_unit/test/ex_unit/doc_test_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Code.require_file "../test_helper.exs", __DIR__
22

3-
import PathHelpers
3+
import ExUnit.TestHelpers
44

55
defmodule ExUnit.DocTestTest.GoodModule do
66
@doc """

0 commit comments

Comments
 (0)