Skip to content

Commit 2efe700

Browse files
committed
Enriched assertion output for is_* guards
1 parent 2ab126e commit 2efe700

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

lib/ex_unit/lib/ex_unit/assertions.ex

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,24 @@ defmodule ExUnit.Assertions do
269269

270270
@operator [:==, :<, :>, :<=, :>=, :===, :=~, :!==, :!=, :in]
271271

272+
@type_guards [
273+
is_atom: "an atom",
274+
is_binary: "a binary",
275+
is_bitstring: "a bitstring",
276+
is_boolean: "a boolean",
277+
is_float: "a float",
278+
is_function: "a function",
279+
is_integer: "an integer",
280+
is_list: "a list",
281+
is_map: "a map",
282+
is_nil: "nil",
283+
is_number: "a number",
284+
is_pid: "a PID",
285+
is_port: "a port",
286+
is_reference: "a reference",
287+
is_tuple: "a tuple"
288+
]
289+
272290
defp translate_assertion(:assert, {operator, meta, [_, _]} = expr, caller)
273291
when operator in @operator do
274292
if match?([{_, Kernel}], Macro.Env.lookup_import(caller, {operator, 2})) do
@@ -293,6 +311,20 @@ defmodule ExUnit.Assertions do
293311
end
294312
end
295313

314+
defp translate_assertion(:assert, {guard, _meta, [_]} = expr, caller)
315+
when guard in unquote(Keyword.keys(@type_guards)) do
316+
if match?([{_, Kernel}], Macro.Env.lookup_import(caller, {guard, 1})) do
317+
translate_bool_guard(:assert, expr, "Assertion with #{guard}/1 failed", caller)
318+
end
319+
end
320+
321+
defp translate_assertion(:refute, {guard, _meta, [_]} = expr, caller)
322+
when guard in unquote(Keyword.keys(@type_guards)) do
323+
if match?([{_, Kernel}], Macro.Env.lookup_import(caller, {guard, 1})) do
324+
translate_bool_guard(:refute, expr, "Refute with #{guard}/1 failed", caller)
325+
end
326+
end
327+
296328
defp translate_assertion(_kind, _expected, _caller) do
297329
nil
298330
end
@@ -343,6 +375,32 @@ defmodule ExUnit.Assertions do
343375
end
344376
end
345377

378+
defp translate_bool_guard(kind, {guard, meta, [arg]} = expr, message, _caller) do
379+
expr = escape_quoted(kind, meta, expr)
380+
call = {guard, meta, [arg]}
381+
call = if kind == :assert, do: call, else: {:not, meta, [call]}
382+
383+
human_type =
384+
case kind do
385+
:assert -> "not #{type_guard_to_human_readable(guard)}"
386+
:refute -> type_guard_to_human_readable(guard)
387+
end
388+
389+
quote do
390+
arg = unquote(arg)
391+
392+
ExUnit.Assertions.assert(unquote(call),
393+
left: arg,
394+
expr: unquote(expr),
395+
message: unquote(message) <> ", the given expression is #{unquote(human_type)}"
396+
)
397+
end
398+
end
399+
400+
for {guard_name, human_name} <- @type_guards do
401+
defp type_guard_to_human_readable(unquote(guard_name)), do: unquote(human_name)
402+
end
403+
346404
@doc false
347405
def __equal__?(left, right) do
348406
left === right

0 commit comments

Comments
 (0)