diff --git a/lib/ex_unit/lib/ex_unit/assertions.ex b/lib/ex_unit/lib/ex_unit/assertions.ex index 1bbb3bc96c7..ee3b91cc120 100644 --- a/lib/ex_unit/lib/ex_unit/assertions.ex +++ b/lib/ex_unit/lib/ex_unit/assertions.ex @@ -3,6 +3,8 @@ defmodule ExUnit.AssertionError do Raised to signal an assertion error. """ + alias ExUnit.Formatter, as: F + @no_value :ex_unit_no_meaningful_value defexception left: @no_value, @@ -16,6 +18,12 @@ defmodule ExUnit.AssertionError do def no_value do @no_value end + + def message(assertion_error) do + "\n\n" <> F.format_assertion_error(assertion_error, :infinity, &formatter/2, "") + end + + defp formatter(_, msg), do: msg end defmodule ExUnit.MultiError do diff --git a/lib/ex_unit/lib/ex_unit/cli_formatter.ex b/lib/ex_unit/lib/ex_unit/cli_formatter.ex index 88b1a73da3b..cde8f89caa3 100644 --- a/lib/ex_unit/lib/ex_unit/cli_formatter.ex +++ b/lib/ex_unit/lib/ex_unit/cli_formatter.ex @@ -197,7 +197,7 @@ defmodule ExUnit.CLIFormatter do colorize(:red, msg, config) end - defp formatter(:colors_enabled?, _, %{colors: colors}), + defp formatter(:diff_enabled?, _, %{colors: colors}), do: colors[:enabled] defp formatter(:error_info, msg, config), diff --git a/lib/ex_unit/lib/ex_unit/formatter.ex b/lib/ex_unit/lib/ex_unit/formatter.ex index 61034d656cf..c3649c6e54c 100644 --- a/lib/ex_unit/lib/ex_unit/formatter.ex +++ b/lib/ex_unit/lib/ex_unit/formatter.ex @@ -118,6 +118,30 @@ defmodule ExUnit.Formatter do <> report(tags, failures, width, formatter) end + @doc false + def format_assertion_error(%ExUnit.AssertionError{} = struct, width, formatter, counter_padding \\ @counter_padding) do + padding_size = byte_size(@inspect_padding) + + fields = [ + note: if_value(struct.message, &format_banner(&1, formatter)), + code: if_value(struct.expr, &code_multiline(&1, padding_size)), + lhs: if_value(struct.left, &inspect_multiline(&1, padding_size, width)), + rhs: if_value(struct.right, &inspect_multiline(&1, padding_size, width)) + ] + + fields = + if formatter.(:diff_enabled?, nil) == true do + fields ++ [diff: format_diff(struct, formatter)] + else + fields + end + + fields + |> filter_interesting_fields() + |> format_each_field(formatter) + |> make_into_lines(counter_padding) + end + defp report(tags, failures, width, formatter) do case Map.take(tags, List.wrap(tags[:report])) do report when map_size(report) == 0 -> @@ -149,22 +173,7 @@ defmodule ExUnit.Formatter do end defp format_kind_reason(:error, %ExUnit.AssertionError{} = struct, width, formatter) do - padding_size = byte_size(@inspect_padding) - - fields = [ - note: if_value(struct.message, &format_banner(&1, formatter)), - code: if_value(struct.expr, &code_multiline(&1, padding_size)), - lhs: if_value(struct.left, &inspect_multiline(&1, padding_size, width)), - rhs: if_value(struct.right, &inspect_multiline(&1, padding_size, width)) - ] - if formatter.(:colors_enabled?, nil) do - fields ++ [diff: format_diff(struct, formatter)] - else - fields - end - |> filter_interesting_fields() - |> format_each_field(formatter) - |> make_into_lines(@counter_padding) + format_assertion_error(struct, width, formatter) end defp format_kind_reason(kind, reason, _width, formatter) do diff --git a/lib/ex_unit/test/ex_unit/assertions_test.exs b/lib/ex_unit/test/ex_unit/assertions_test.exs index 04312e44a8d..7c899a4600f 100644 --- a/lib/ex_unit/test/ex_unit/assertions_test.exs +++ b/lib/ex_unit/test/ex_unit/assertions_test.exs @@ -593,6 +593,19 @@ defmodule ExUnit.AssertionsTest do "no function clause matching in ExUnit.Assertions.flunk/1" = FunctionClauseError.message error end + test "AssertionError message should include nice formatting" do + assert :a = :b + rescue + error in [ExUnit.AssertionError] -> + """ + + + match (=) failed + code: :a = :b + rhs: :b + """ = Exception.message(error) + end + defp ok(val), do: {:ok, val} defp error(val), do: {:error, val} end