diff options
| author | Eric Meadows-Jönsson <eric.meadows.jonsson@gmail.com> | 2015-05-11 00:34:33 +0200 |
|---|---|---|
| committer | Eric Meadows-Jönsson <eric.meadows.jonsson@gmail.com> | 2015-05-11 00:34:33 +0200 |
| commit | b463286ead4fd6d8c0d843d782fa51e7d52d24a5 (patch) | |
| tree | daca566fcaa844d5962a736a3ea73a1085513b3a | |
| parent | 09bf62e6996b91e70c6083a2ec7a14508f7a632e (diff) | |
| download | elixir-emj-multi-assert.tar.gz | |
Collect and display subsequent assert errorsemj-multi-assert
| -rw-r--r-- | lib/elixir/test/elixir/kernel/import_test.exs | 2 | ||||
| -rw-r--r-- | lib/ex_unit/lib/ex_unit.ex | 7 | ||||
| -rw-r--r-- | lib/ex_unit/lib/ex_unit/assertions.ex | 37 | ||||
| -rw-r--r-- | lib/ex_unit/lib/ex_unit/failure_collector.ex | 21 | ||||
| -rw-r--r-- | lib/ex_unit/lib/ex_unit/formatter.ex | 20 | ||||
| -rw-r--r-- | lib/ex_unit/lib/ex_unit/runner.ex | 30 | ||||
| -rw-r--r-- | lib/ex_unit/mix.exs | 5 | ||||
| -rw-r--r-- | lib/ex_unit/test/ex_unit/assertions_test.exs | 310 | ||||
| -rw-r--r-- | lib/ex_unit/test/ex_unit/capture_io_test.exs | 6 | ||||
| -rw-r--r-- | lib/ex_unit/test/ex_unit/formatter_test.exs | 46 |
10 files changed, 251 insertions, 233 deletions
diff --git a/lib/elixir/test/elixir/kernel/import_test.exs b/lib/elixir/test/elixir/kernel/import_test.exs index 49f9f9f80..a1897d91c 100644 --- a/lib/elixir/test/elixir/kernel/import_test.exs +++ b/lib/elixir/test/elixir/kernel/import_test.exs @@ -149,7 +149,7 @@ defmodule Kernel.ImportTest do try do import :lists flatten([1, [2], 3]) - flunk + raise "go to catch clause" catch _, _ -> # Buggy local duplicate is untouched diff --git a/lib/ex_unit/lib/ex_unit.ex b/lib/ex_unit/lib/ex_unit.ex index 7909261a7..06cc5d780 100644 --- a/lib/ex_unit/lib/ex_unit.ex +++ b/lib/ex_unit/lib/ex_unit.ex @@ -58,8 +58,8 @@ defmodule ExUnit do """ @typedoc "The state returned by ExUnit.Test and ExUnit.TestCase" - @type state :: nil | {:failed, failed} | {:skip, binary} | {:invalid, module} - @type failed :: {Exception.kind, reason :: term, stacktrace :: [tuple]} + @type state :: nil | {:failed, failures} | {:skip, binary} | {:invalid, module} + @type failures :: [{Exception.kind, reason :: term, stacktrace :: [tuple]}] defmodule Test do @moduledoc """ @@ -128,7 +128,8 @@ defmodule ExUnit do children = [ worker(ExUnit.Server, []), - worker(ExUnit.OnExitHandler, []) + worker(ExUnit.OnExitHandler, []), + worker(ExUnit.FailureCollector, []) ] opts = [strategy: :one_for_one, name: ExUnit.Supervisor] diff --git a/lib/ex_unit/lib/ex_unit/assertions.ex b/lib/ex_unit/lib/ex_unit/assertions.ex index 3361708c0..7909b3be7 100644 --- a/lib/ex_unit/lib/ex_unit/assertions.ex +++ b/lib/ex_unit/lib/ex_unit/assertions.ex @@ -35,6 +35,19 @@ defmodule ExUnit.Assertions do common cases such as checking a floating point number or handling exceptions. """ + @doc false + defmacro raise_assert(opts) do + quote do + try do + raise ExUnit.AssertionError, unquote(opts) + catch + :error, %ExUnit.AssertionError{} = error -> + stacktrace = System.stacktrace + ExUnit.FailureCollector.add_failure(self, {:error, error, stacktrace}) + end + end + end + @doc """ Asserts its argument is `true`. @@ -71,10 +84,10 @@ defmodule ExUnit.Assertions do unquote(left) -> right _ -> - raise ExUnit.AssertionError, + raise_assert( right: right, expr: unquote(code), - message: "match (=) failed" + message: "match (=) failed") end end @@ -91,9 +104,9 @@ defmodule ExUnit.Assertions do value = unquote(assertion) unless value do - raise ExUnit.AssertionError, + raise_assert( expr: unquote(Macro.escape(assertion)), - message: "Expected truthy, got #{inspect value}" + message: "Expected truthy, got #{inspect value}") end value @@ -119,10 +132,10 @@ defmodule ExUnit.Assertions do quote do case right do unquote(left) -> - raise ExUnit.AssertionError, + raise_assert( right: right, expr: unquote(code), - message: "match (=) succeeded, but should have failed" + message: "match (=) succeeded, but should have failed") _ -> right end @@ -141,9 +154,9 @@ defmodule ExUnit.Assertions do value = unquote(assertion) if value do - raise ExUnit.AssertionError, + raise_assert( expr: unquote(Macro.escape(assertion)), - message: "Expected false or nil, got #{inspect value}" + message: "Expected false or nil, got #{inspect value}") end value @@ -203,7 +216,7 @@ defmodule ExUnit.Assertions do end def assert(value, opts) when is_list(opts) do - unless value, do: raise(ExUnit.AssertionError, opts) + unless value, do: raise_assert(opts) true end @@ -345,14 +358,11 @@ defmodule ExUnit.Assertions do function.() rescue error -> - stacktrace = System.stacktrace name = error.__struct__ cond do name == exception -> error - name == ExUnit.AssertionError -> - reraise(error, stacktrace) true -> flunk "Expected exception #{inspect exception} but got #{inspect name} (#{Exception.message(error)})" end @@ -423,9 +433,6 @@ defmodule ExUnit.Assertions do try do unquote(expr) flunk "Expected to catch #{unquote(kind)}, got nothing" - rescue - e in [ExUnit.AssertionError] -> - reraise(e, System.stacktrace) catch unquote(kind), we_got -> we_got end diff --git a/lib/ex_unit/lib/ex_unit/failure_collector.ex b/lib/ex_unit/lib/ex_unit/failure_collector.ex new file mode 100644 index 000000000..45ad3d8eb --- /dev/null +++ b/lib/ex_unit/lib/ex_unit/failure_collector.ex @@ -0,0 +1,21 @@ +defmodule ExUnit.FailureCollector do + @moduledoc false + @name __MODULE__ + + def start_link do + Agent.start_link(fn -> %{} end, name: @name) + end + + def add_failure(pid, failure) do + Agent.update(@name, fn map -> + Map.update(map, pid, [failure], &[failure|&1]) + end) + end + + def get_failures(pid) do + Agent.get_and_update(@name, fn map -> + {failures, map} = Map.pop(map, pid) + {Enum.reverse(failures || []), map} + end) + end +end diff --git a/lib/ex_unit/lib/ex_unit/formatter.ex b/lib/ex_unit/lib/ex_unit/formatter.ex index 1d6f64dd7..10a638713 100644 --- a/lib/ex_unit/lib/ex_unit/formatter.ex +++ b/lib/ex_unit/lib/ex_unit/formatter.ex @@ -105,24 +105,28 @@ defmodule ExUnit.Formatter do @doc """ Receives a test and formats its failure. """ - def format_test_failure(test, failure, counter, width, formatter) - def format_test_failure(test, {kind, reason, stack}, counter, width, formatter) do + def format_test_failure(test, failures, counter, width, formatter) + def format_test_failure(test, failures, counter, width, formatter) do %ExUnit.Test{name: name, case: case, tags: tags} = test test_info(with_counter(counter, "#{name} (#{inspect case})"), formatter) <> test_location(with_location(tags), formatter) - <> format_kind_reason(kind, reason, width, formatter) - <> format_stacktrace(stack, case, name, formatter) + <> Enum.map_join(failures, "\n", fn {kind, reason, stack} -> + format_kind_reason(kind, reason, width, formatter) + <> format_stacktrace(stack, case, name, formatter) + end) end @doc """ Receives a test case and formats its failure. """ - def format_test_case_failure(test_case, failure, counter, width, formatter) - def format_test_case_failure(test_case, {kind, reason, stacktrace}, counter, width, formatter) do + def format_test_case_failure(test_case, failures, counter, width, formatter) + def format_test_case_failure(test_case, failures, counter, width, formatter) do %ExUnit.TestCase{name: name} = test_case test_case_info(with_counter(counter, "#{inspect name}: "), formatter) - <> format_kind_reason(kind, reason, width, formatter) - <> format_stacktrace(stacktrace, name, nil, formatter) + <> Enum.map_join(failures, "\n", fn {kind, reason, stack} -> + format_kind_reason(kind, reason, width, formatter) + <> format_stacktrace(stack, name, nil, formatter) + end) end defp format_kind_reason(:error, %ExUnit.AssertionError{} = struct, width, formatter) do diff --git a/lib/ex_unit/lib/ex_unit/runner.ex b/lib/ex_unit/lib/ex_unit/runner.ex index 6396fdeee..93f2c362b 100644 --- a/lib/ex_unit/lib/ex_unit/runner.ex +++ b/lib/ex_unit/lib/ex_unit/runner.ex @@ -171,7 +171,7 @@ defmodule ExUnit.Runner do end {test_case, tests} {:DOWN, ^case_ref, :process, ^case_pid, error} -> - test_case = %{test_case | state: {:failed, {{:EXIT, case_pid}, error, []}}} + test_case = add_failure(test_case, {{:EXIT, case_pid}, error, []}) {test_case, []} end @@ -183,8 +183,8 @@ defmodule ExUnit.Runner do {:ok, test_case, context} catch kind, error -> - failed = {:failed, {kind, Exception.normalize(kind, error), pruned_stacktrace}} - {:error, %{test_case | state: failed}} + test_case = add_failure(test_case, {kind, Exception.normalize(kind, error), pruned_stacktrace}) + {:error, test_case} end defp run_test(config, test, context) do @@ -226,9 +226,10 @@ defmodule ExUnit.Runner do receive do {:DOWN, ^test_ref, :process, ^test_pid, _} -> :ok end - test + failures = ExUnit.FailureCollector.get_failures(test_pid) + add_failure(test, failures) {:DOWN, ^test_ref, :process, ^test_pid, error} -> - %{test | state: {:failed, {{:EXIT, test_pid}, error, []}}} + add_failure(test, {{:EXIT, test_pid}, error, []}) after timeout -> stacktrace = @@ -241,7 +242,7 @@ defmodule ExUnit.Runner do end Process.exit(test_pid, :kill) Process.demonitor(test_ref, [:flush]) - %{test | state: {:failed, {:error, %ExUnit.TimeoutError{timeout: timeout}, stacktrace}}} + add_failure(test, {:error, %ExUnit.TimeoutError{timeout: timeout}, stacktrace}) end exec_on_exit(test, test_pid) @@ -252,8 +253,8 @@ defmodule ExUnit.Runner do {:ok, test, context} catch kind2, error2 -> - failed = {:failed, {kind2, Exception.normalize(kind2, error2), pruned_stacktrace()}} - {:error, %{test | state: failed}} + test = add_failure(test, {kind2, Exception.normalize(kind2, error2), pruned_stacktrace()}) + {:error, test} end defp exec_test(%ExUnit.Test{case: case, name: name} = test, context) do @@ -261,8 +262,7 @@ defmodule ExUnit.Runner do test catch kind, error -> - failed = {:failed, {kind, Exception.normalize(kind, error), pruned_stacktrace()}} - %{test | state: failed} + add_failure(test, {kind, Exception.normalize(kind, error), pruned_stacktrace()}) end defp exec_on_exit(test_or_case, pid) do @@ -270,13 +270,19 @@ defmodule ExUnit.Runner do :ok -> test_or_case {kind, reason, stack} -> - state = test_or_case.state || {:failed, {kind, reason, prune_stacktrace(stack)}} - %{test_or_case | state: state} + add_failure(test_or_case, {kind, reason, prune_stacktrace(stack)}) end end ## Helpers + defp add_failure(test, []), + do: test + defp add_failure(%{state: {:failed, failures}} = test, failure), + do: %{test | state: {:failed, List.wrap(failure) ++ failures}} + defp add_failure(test, failure), + do: %{test | state: {:failed, List.wrap(failure)}} + defp shuffle(%{seed: 0}, list) do Enum.reverse(list) end diff --git a/lib/ex_unit/mix.exs b/lib/ex_unit/mix.exs index 44a5337ed..0ee667a3e 100644 --- a/lib/ex_unit/mix.exs +++ b/lib/ex_unit/mix.exs @@ -8,7 +8,10 @@ defmodule ExUnit.Mixfile do end def application do - [registered: [ExUnit.Server], + [registered: [ + ExUnit.Server, + ExUnit.OnExitHandler, + ExUnit.FailureCollector], mod: {ExUnit, []}, env: [ # Calculated on demand diff --git a/lib/ex_unit/test/ex_unit/assertions_test.exs b/lib/ex_unit/test/ex_unit/assertions_test.exs index e5b5899c7..b4cdd5bf7 100644 --- a/lib/ex_unit/test/ex_unit/assertions_test.exs +++ b/lib/ex_unit/test/ex_unit/assertions_test.exs @@ -11,49 +11,44 @@ alias ExUnit.AssertionsTest.Value defmodule ExUnit.AssertionsTest do use ExUnit.Case, async: true + defp assert_error do + [{:error, error, _}] = ExUnit.FailureCollector.get_failures(self) + error + end + test "assert with true value" do true = assert Value.truthy end test "assert with message when value is false" do - try do - "This should never be tested" = assert false, "This should be true" - rescue - error in [ExUnit.AssertionError] -> - "This should be true" = error.message - end + assert false, "This should be true" + "This should be true" = assert_error().message end test "assert when value evaluates to false" do - try do - "This should never be tested" = assert Value.falsy - rescue - error in [ExUnit.AssertionError] -> - "Value.falsy()" = error.expr |> Macro.to_string - "Expected truthy, got false" = error.message - end + assert Value.falsy + + error = assert_error() + "Value.falsy()" = error.expr |> Macro.to_string + "Expected truthy, got false" = error.message end test "assert with equality" do - try do - "This should never be tested" = assert 1 + 1 == 1 - rescue - error in [ExUnit.AssertionError] -> - 1 = error.right - 2 = error.left - "1 + 1 == 1" = error.expr |> Macro.to_string - end + assert 1 + 1 == 1 + + error = assert_error() + 1 = error.right + 2 = error.left + "1 + 1 == 1" = error.expr |> Macro.to_string end test "assert with equality in reverse" do - try do - "This should never be tested" = assert 1 == 1 + 1 - rescue - error in [ExUnit.AssertionError] -> - 1 = error.left - 2 = error.right - "1 == 1 + 1" = error.expr |> Macro.to_string - end + assert 1 == 1 + 1 + + error = assert_error() + 1 = error.left + 2 = error.right + "1 == 1 + 1" = error.expr |> Macro.to_string end test "refute when value is false" do @@ -61,14 +56,10 @@ defmodule ExUnit.AssertionsTest do end test "refute when value evaluates to true" do - try do - refute Value.truthy - raise "refute was supposed to fail" - rescue - error in [ExUnit.AssertionError] -> - "Value.truthy()" = error.expr |> Macro.to_string - "Expected false or nil, got true" = error.message - end + refute Value.truthy + error = assert_error() + "Value.truthy()" = error.expr |> Macro.to_string + "Expected false or nil, got true" = error.message end test "assert match when equal" do @@ -87,35 +78,28 @@ defmodule ExUnit.AssertionsTest do end test "assert received when empty mailbox" do - try do - "This should never be tested" = assert_received :hello - rescue - error in [ExUnit.AssertionError] -> - "No message matching :hello after 0ms. The process mailbox is empty." = error.message - end + assert_received :hello + error = assert_error() + "No message matching :hello after 0ms. The process mailbox is empty." = error.message end test "assert received when different message" do send self, {:message, :not_expected, :at_all} - try do - "This should never be tested" = assert_received :hello - rescue - error in [ExUnit.AssertionError] -> - "No message matching :hello after 0ms. Process mailbox:\n{:message, :not_expected, :at_all}" = error.message - end + assert_received :hello + + error = assert_error() + "No message matching :hello after 0ms. Process mailbox:\n{:message, :not_expected, :at_all}" = error.message end test "assert received when different message having more than 10 on mailbox" do for i <- 1..11, do: send(self, {:message, i}) - try do - "This should never be tested" = assert_received x when x == :hello - rescue - error in [ExUnit.AssertionError] -> - "No message matching x when x == :hello after 0ms. Process mailbox:\n" <> - "{:message, 1}\n{:message, 2}\n{:message, 3}\n{:message, 4}\n" <> - "{:message, 5}\n{:message, 6}\n{:message, 7}\n{:message, 8}\n" <> - "{:message, 9}\n{:message, 10}\nShowing only 10 of 11 messages." = error.message - end + assert_received x when x == :hello + + error = assert_error() + "No message matching x when x == :hello after 0ms. Process mailbox:\n" <> + "{:message, 1}\n{:message, 2}\n{:message, 3}\n{:message, 4}\n" <> + "{:message, 5}\n{:message, 6}\n{:message, 7}\n{:message, 8}\n" <> + "{:message, 9}\n{:message, 10}\nShowing only 10 of 11 messages." = error.message end test "assert received leaks" do @@ -134,12 +118,10 @@ defmodule ExUnit.AssertionsTest do test "refute received when equal" do send self, :hello - try do - "This should never be tested" = refute_received :hello - rescue - error in [ExUnit.AssertionError] -> - "Unexpectedly received message :hello (which matched :hello)" = error.message - end + refute_received :hello + + error = assert_error() + "Unexpectedly received message :hello (which matched :hello)" = error.message end test "assert in when member" do @@ -147,14 +129,12 @@ defmodule ExUnit.AssertionsTest do end test "assert in when is not member" do - try do - "This should never be tested" = assert 'foo' in 'bar' - rescue - error in [ExUnit.AssertionError] -> - 'foo' = error.left - 'bar' = error.right - "'foo' in 'bar'" = error.expr |> Macro.to_string - end + assert 'foo' in 'bar' + + error = assert_error() + 'foo' = error.left + 'bar' = error.right + "'foo' in 'bar'" = error.expr |> Macro.to_string end test "refute in when is not member" do @@ -162,14 +142,12 @@ defmodule ExUnit.AssertionsTest do end test "refute in when is member" do - try do - "This should never be tested" = refute 'foo' in ['foo', 'bar'] - rescue - error in [ExUnit.AssertionError] -> - 'foo' = error.left - ['foo', 'bar'] = error.right - "'foo' in ['foo', 'bar']" = error.expr |> Macro.to_string - end + refute 'foo' in ['foo', 'bar'] + + error = assert_error() + 'foo' = error.left + ['foo', 'bar'] = error.right + "'foo' in ['foo', 'bar']" = error.expr |> Macro.to_string end test "assert match" do @@ -177,25 +155,21 @@ defmodule ExUnit.AssertionsTest do end test "assert match when no match" do - try do - "This should never be tested" = assert {:ok, _} = "bar" - rescue - error in [ExUnit.AssertionError] -> - "match (=) failed" = error.message - "{:ok, _} = \"bar\"" = error.expr |> Macro.to_string - "bar" = error.right - end + assert {:ok, _} = "bar" + + error = assert_error() + "match (=) failed" = error.message + "{:ok, _} = \"bar\"" = error.expr |> Macro.to_string + "bar" = error.right end test "refute match when no match" do - try do - "This should never be tested" = refute _ = "bar" - rescue - error in [ExUnit.AssertionError] -> - "bar" = error.right - "_ = \"bar\"" = error.expr |> Macro.to_string - "match (=) succeeded, but should have failed" = error.message - end + refute _ = "bar" + + error = assert_error() + "bar" = error.right + "_ = \"bar\"" = error.expr |> Macro.to_string + "match (=) succeeded, but should have failed" = error.message end test "assert regex match" do @@ -203,13 +177,11 @@ defmodule ExUnit.AssertionsTest do end test "assert regex match when no match" do - try do - "This should never be tested" = assert "foo" =~ ~r(a) - rescue - error in [ExUnit.AssertionError] -> - "foo" = error.left - ~r{a} = error.right - end + assert "foo" =~ ~r(a) + + error = assert_error() + "foo" = error.left + ~r{a} = error.right end test "refute regex match" do @@ -217,49 +189,43 @@ defmodule ExUnit.AssertionsTest do end test "refute regex match when match" do - try do - "This should never be tested" = refute "foo" =~ ~r(o) - rescue - error in [ExUnit.AssertionError] -> - "foo" = error.left - ~r"o" = error.right - end + refute "foo" =~ ~r(o) + + error = assert_error() + "foo" = error.left + ~r"o" = error.right end test "assert raise with no error" do - "This should never be tested" = assert_raise ArgumentError, fn -> + assert_raise ArgumentError, fn -> # nothing end - rescue - error in [ExUnit.AssertionError] -> - "Expected exception ArgumentError but nothing was raised" = error.message + error = assert_error() + "Expected exception ArgumentError but nothing was raised" = error.message end test "assert raise with error" do error = assert_raise ArgumentError, fn -> raise ArgumentError, "test error" end - "test error" = error.message end test "assert raise with some other error" do - "This should never be tested" = assert_raise ArgumentError, fn -> + assert_raise ArgumentError, fn -> Not.Defined.function(1, 2, 3) end - rescue - error in [ExUnit.AssertionError] -> - "Expected exception ArgumentError but got UndefinedFunctionError " <> - "(undefined function: Not.Defined.function/3 (module Not.Defined is not available))" = error.message + error = assert_error() + "Expected exception ArgumentError but got UndefinedFunctionError " <> + "(undefined function: Not.Defined.function/3 (module Not.Defined is not available))" = error.message end test "assert raise with erlang error" do assert_raise SyntaxError, fn -> List.flatten(1) end - rescue - error in [ExUnit.AssertionError] -> - "Expected exception SyntaxError but got FunctionClauseError (no function clause matching in :lists.flatten/1)" = error.message + error = assert_error() + "Expected exception SyntaxError but got FunctionClauseError (no function clause matching in :lists.flatten/1)" = error.message end test "assert greater than operator" do @@ -267,12 +233,12 @@ defmodule ExUnit.AssertionsTest do end test "assert greater than operator error" do - "This should never be tested" = assert 1 > 2 - rescue - error in [ExUnit.AssertionError] -> - 1 = error.left - 2 = error.right - "1 > 2" = error.expr |> Macro.to_string + assert 1 > 2 + + error = assert_error() + 1 = error.left + 2 = error.right + "1 > 2" = error.expr |> Macro.to_string end test "assert less or equal than operator" do @@ -280,12 +246,12 @@ defmodule ExUnit.AssertionsTest do end test "assert less or equal than operator error" do - "This should never be tested" = assert 2 <= 1 - rescue - error in [ExUnit.AssertionError] -> - "2 <= 1" = error.expr |> Macro.to_string - 2 = error.left - 1 = error.right + assert 2 <= 1 + + error = assert_error() + "2 <= 1" = error.expr |> Macro.to_string + 2 = error.left + 1 = error.right end test "assert operator with expressions" do @@ -294,10 +260,10 @@ defmodule ExUnit.AssertionsTest do end test "assert operator with custom message" do - "This should never be tested" = assert 1 > 2, "assertion" - rescue - error in [ExUnit.AssertionError] -> - "assertion" = error.message + assert 1 > 2, "assertion" + + error = assert_error() + "assertion" = error.message end test "assert in delta" do @@ -305,17 +271,17 @@ defmodule ExUnit.AssertionsTest do end test "assert in delta error" do - "This should never be tested" = assert_in_delta(10, 12, 1) - rescue - error in [ExUnit.AssertionError] -> - "Expected the difference between 10 and 12 (2) to be less than 1" = error.message + assert_in_delta(10, 12, 1) + + error = assert_error() + "Expected the difference between 10 and 12 (2) to be less than 1" = error.message end test "assert in delta with message" do - "This should never be tested" = assert_in_delta(10, 12, 1, "test message") - rescue - error in [ExUnit.AssertionError] -> - "test message" = error.message + assert_in_delta(10, 12, 1, "test message") + + error = assert_error() + "test message" = error.message end test "refute in delta" do @@ -323,38 +289,38 @@ defmodule ExUnit.AssertionsTest do end test "refute in delta error" do - "This should never be tested" = refute_in_delta(10, 11, 2) - rescue - error in [ExUnit.AssertionError] -> - "Expected the difference between 10 and 11 (1) to be more than 2" = error.message + refute_in_delta(10, 11, 2) + + error = assert_error() + "Expected the difference between 10 and 11 (1) to be more than 2" = error.message end test "refute in delta with message" do - "This should never be tested" = refute_in_delta(10, 11, 2, "test message") - rescue - error in [ExUnit.AssertionError] -> - "test message (difference between 10 and 11 is less than 2)" = error.message + refute_in_delta(10, 11, 2, "test message") + + error = assert_error() + "test message (difference between 10 and 11 is less than 2)" = error.message end test "catch_throw with no throw" do catch_throw(1) - rescue - error in [ExUnit.AssertionError] -> - "Expected to catch throw, got nothing" = error.message + + error = assert_error() + "Expected to catch throw, got nothing" = error.message end test "catch_error with no error" do catch_error(1) - rescue - error in [ExUnit.AssertionError] -> - "Expected to catch error, got nothing" = error.message + + error = assert_error() + "Expected to catch error, got nothing" = error.message end test "catch_exit with no exit" do catch_exit(1) - rescue - error in [ExUnit.AssertionError] -> - "Expected to catch exit, got nothing" = error.message + + error = assert_error() + "Expected to catch exit, got nothing" = error.message end test "catch_throw with throw" do @@ -370,17 +336,17 @@ defmodule ExUnit.AssertionsTest do end test "flunk" do - "This should never be tested" = flunk - rescue - error in [ExUnit.AssertionError] -> - "Flunked!" = error.message + flunk + + error = assert_error() + "Flunked!" = error.message end test "flunk with message" do - "This should never be tested" = flunk "This should raise an error" - rescue - error in [ExUnit.AssertionError] -> - "This should raise an error" = error.message + flunk "This should raise an error" + + error = assert_error() + "This should raise an error" = error.message end test "flunk with wrong argument type" do diff --git a/lib/ex_unit/test/ex_unit/capture_io_test.exs b/lib/ex_unit/test/ex_unit/capture_io_test.exs index 87677c79d..3915e9463 100644 --- a/lib/ex_unit/test/ex_unit/capture_io_test.exs +++ b/lib/ex_unit/test/ex_unit/capture_io_test.exs @@ -294,11 +294,11 @@ defmodule ExUnit.CaptureIOTest do try do capture_io(fn -> - assert false + raise "message" end) rescue - error in [ExUnit.AssertionError] -> - "Expected truthy, got false" = error.message + error in [RuntimeError] -> + "message" = error.message end # Ensure no leakage on failures diff --git a/lib/ex_unit/test/ex_unit/formatter_test.exs b/lib/ex_unit/test/ex_unit/formatter_test.exs index 923c135e6..3db844216 100644 --- a/lib/ex_unit/test/ex_unit/formatter_test.exs +++ b/lib/ex_unit/test/ex_unit/formatter_test.exs @@ -11,11 +11,9 @@ defmodule ExUnit.FormatterTest do defmacrop catch_assertion(expr) do quote do - try do - unquote(expr) - rescue - e -> e - end + unquote(expr) + [{:error, error, _}] = ExUnit.FailureCollector.get_failures(self) + error end end @@ -34,7 +32,7 @@ defmodule ExUnit.FormatterTest do end test "formats test errors" do - failure = {:error, catch_error(raise "oops"), []} + failure = [{:error, catch_error(raise "oops"), []}] assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 @@ -43,7 +41,7 @@ defmodule ExUnit.FormatterTest do end test "formats test exits" do - failure = {:exit, 1, []} + failure = [{:exit, 1, []}] assert format_test_failure(test(), failure, 1, 80, &formatter/2) == """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 @@ -52,7 +50,7 @@ defmodule ExUnit.FormatterTest do end test "formats test exits with mfa" do - failure = {:exit, {:bye, {:m, :f, []}}, []} + failure = [{:exit, {:bye, {:m, :f, []}}, []}] assert format_test_failure(test(), failure, 1, 80, &formatter/2) == """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 @@ -62,7 +60,7 @@ defmodule ExUnit.FormatterTest do end test "formats test throws" do - failure = {:throw, 1, []} + failure = [{:throw, 1, []}] assert format_test_failure(test(), failure, 1, 80, &formatter/2) == """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 @@ -71,7 +69,7 @@ defmodule ExUnit.FormatterTest do end test "formats test EXITs" do - failure = {{:EXIT, self}, 1, []} + failure = [{{:EXIT, self}, 1, []}] assert format_test_failure(test(), failure, 1, 80, &formatter/2) == """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 @@ -80,7 +78,7 @@ defmodule ExUnit.FormatterTest do end test "formats stacktraces" do - failure = {:error, catch_error(raise "oops"), [{Oops, :wrong, 1, [file: "formatter_test.exs", line: 1]}]} + failure = [{:error, catch_error(raise "oops"), [{Oops, :wrong, 1, [file: "formatter_test.exs", line: 1]}]}] assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 @@ -91,7 +89,7 @@ defmodule ExUnit.FormatterTest do end test "formats assertions" do - failure = {:error, catch_assertion(assert ExUnit.FormatterTest.falsy), []} + failure = [{:error, catch_assertion(assert ExUnit.FormatterTest.falsy), []}] assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ 1) world (Hello) test/ex_unit/formatter_test.exs:1 @@ -101,7 +99,7 @@ defmodule ExUnit.FormatterTest do end test "formats test case errors" do - failure = {:error, catch_error(raise "oops"), []} + failure = [{:error, catch_error(raise "oops"), []}] assert format_test_case_failure(case(), failure, 1, 80, &formatter/2) =~ """ 1) Hello: failure on setup_all callback, tests invalidated ** (RuntimeError) oops @@ -109,7 +107,7 @@ defmodule ExUnit.FormatterTest do end test "formats assertions with operators with no limit" do - failure = {:error, catch_assertion(assert [1, 2, 3] == [4, 5, 6]), []} + failure = [{:error, catch_assertion(assert [1, 2, 3] == [4, 5, 6]), []}] assert format_test_case_failure(case(), failure, 1, :infinity, &formatter/2) =~ """ 1) Hello: failure on setup_all callback, tests invalidated Assertion with == failed @@ -120,7 +118,7 @@ defmodule ExUnit.FormatterTest do end test "formats assertions with operators with column limit" do - failure = {:error, catch_assertion(assert [1, 2, 3] == [4, 5, 6]), []} + failure = [{:error, catch_assertion(assert [1, 2, 3] == [4, 5, 6]), []}] assert format_test_case_failure(case(), failure, 1, 15, &formatter/2) =~ """ 1) Hello: failure on setup_all callback, tests invalidated Assertion with == failed @@ -136,7 +134,7 @@ defmodule ExUnit.FormatterTest do test "formats assertions with message with multiple lines" do message = "Some meaningful error:\nuseful info\nanother useful info" - failure = {:error, catch_assertion(assert(false, message)), []} + failure = [{:error, catch_assertion(assert(false, message)), []}] assert format_test_case_failure(case(), failure, 1, :infinity, &formatter/2) =~ """ 1) Hello: failure on setup_all callback, tests invalidated Some meaningful error: @@ -156,7 +154,7 @@ defmodule ExUnit.FormatterTest do end test "inspect failure" do - failure = {:error, catch_assertion(assert :will_fail == %BadInspect{}), []} + failure = [{:error, catch_assertion(assert :will_fail == %BadInspect{}), []}] message = "got FunctionClauseError with message `no function clause matching " <> "in Inspect.ExUnit.FormatterTest.BadInspect.inspect/2` while inspecting " <> @@ -181,7 +179,7 @@ defmodule ExUnit.FormatterTest do end test "message failure" do - failure = {:error, catch_error(raise BadMessage), []} + failure = [{:error, catch_error(raise BadMessage), []}] message = "got RuntimeError with message `oops` while retrieving Exception.message/1 " <> "for %ExUnit.FormatterTest.BadMessage{key: 0}" assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ @@ -190,4 +188,16 @@ defmodule ExUnit.FormatterTest do ** (ExUnit.FormatterTest.BadMessage) #{message} """ end + + test "format multiple errors" do + failure = [{:error, catch_error(raise "oh no"), []}, + {:error, catch_error(raise "oops"), []}] + assert format_test_failure(test(), failure, 1, 80, &formatter/2) =~ """ + 1) world (Hello) + test/ex_unit/formatter_test.exs:1 + ** (RuntimeError) oh no + + ** (RuntimeError) oops + """ + end end |
