@@ -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