Although all the functionality of EUnit is avaliable even without the use of preprocessor macros, the EUnit header file defines a number of such macros in order to make it as easy as possible to write unit tests as compactly as possible and without getting too many details in the way.
Except where explicitly stated, using EUnit macros will never introduce run-time dependencies on the EUnit library code, regardless of whether your code is compiled with testing enabled or disabled.
_test(Expr)
Expr
into a "test object", by wrapping it in a fun-expression and a source line number. Technically, this is the same as
{?LINE, fun () -> (Expr) end}
.
EUNIT
true
whenever EUnit is enabled at compile time. This is typically used to place testing code within conditional compilation, as in:
-ifdef(EUNIT). % test code here ... -endif.e.g., to ensure that the code can be compiled without including the EUnit header file, when testing is disabled. See also the macros
TEST
and
NOTEST
.
EUNIT_NOAUTO
TEST
This macro is always defined (to true
, unless previously defined by the user to have another value) whenever EUnit is enabled at compile time. This can be used to place testing code within conditional compilation; see also the macros NOTEST
and EUNIT
.
For testing code that is strictly dependent on EUnit, it may be preferable to use the EUNIT
macro for this purpose, while for code that uses more generic testing conventions, using the TEST
macro may be preferred.
TEST
macro can also be used to override the
NOTEST
macro. If
TEST
is defined
before the EUnit header file is included (even if
NOTEST
is also defined), then the code will be compiled with EUnit enabled.
NOTEST
This macro is always defined (to true
, unless previously defined by the user to have another value) whenever EUnit is disabled at compile time. (Compare the TEST
macro.)
NOTEST
is defined
before the EUnit header file is included, and
TEST
is
not defined, then the code will be compiled with EUnit disabled. See also
Disabling testing.
NOASSERT
ASSERT
NODEBUG
NODEBUG
also implies
NOASSERT
, unless testing is enabled.
DEBUG
The following macros can make tests more compact and readable:
LET(Var,Arg,Expr)
Var = Arg
in
Expr
. (This is the same as
(fun(Var)->(Expr)end)(Arg)
.) Note that the binding is not exported outside of
Expr
, and that within
Expr
, this binding of
Var
will shadow any binding of
Var
in the surrounding scope.
IF(Cond,TrueCase,FalseCase)
TrueCase
if
Cond
evaluates to
true
, or otherwise evaluates
FalseCase
if
Cond
evaluates to
false
. (This is the same as
(case (Cond) of true->(TrueCase); false->(FalseCase) end)
.) Note that it is an error if
Cond
does not yield a boolean value.
(Note that these macros also have corresponding forms which start with an "_
" (underscore) character, as in ?_assert(BoolExpr)
, that create a "test object" instead of performing the test immediately. This is equivalent to writing ?_test(assert(BoolExpr))
, etc.)
If the macro NOASSERT
is defined before the EUnit header file is included, these macros have no effect when testing is also disabled; see Compilation control macros for details.
assert(BoolExpr)
Evaluates the expression BoolExpr
, if testing is enabled. Unless the result is true
, an informative exception will be generated. If there is no exception, the result of the macro expression is the atom ok
, and the value of BoolExpr
is discarded. If testing is disabled, the macro will not generate any code except the atom ok
, and BoolExpr
will not be evaluated.
?assert(f(X, Y) =:= [])The
assert
macro can be used anywhere in a program, not just in unit tests, to check pre/postconditions and invariants. For example:
some_recursive_function(X, Y, Z) -> ?assert(X + Y > Z), ...
assertNot(BoolExpr)
assert(not (BoolExpr))
.
assertMatch(GuardedPattern, Expr)
Evaluates Expr
and matches the result against GuardedPattern
, if testing is enabled. If the match fails, an informative exception will be generated; see the assert
macro for further details. GuardedPattern
can be anything that you can write on the left hand side of the ->
symbol in a case-clause, except that it cannot contain comma-separated guard tests.
The main reason for using assertMatch
also for simple matches, instead of matching with =
, is that it produces more detailed error messages.
?assertMatch({found, {fred, _}}, lookup(bloggs, Table))
?assertMatch([X|_] when X > 0, binary_to_list(B))
assertEqual(Expect, Expr)
Evaluates the expressions Expect
and Expr
and compares the results for equality, if testing is enabled. If the values are not equal, an informative exception will be generated; see the assert
macro for further details.
assertEqual
is more suitable than than assertMatch
when the left-hand side is a computed value rather than a simple pattern, and gives more details than ?assert(Expect =:= Expr)
.
?assertEqual("b" ++ "a", lists:reverse("ab"))
?assertEqual(foo(X), bar(Y))
assertException(ClassPattern, TermPattern, Expr)
assertError(TermPattern, Expr)
assertExit(TermPattern, Expr)
assertThrow(TermPattern, Expr)
Evaluates Expr
, catching any exception and testing that it matches the expected ClassPattern:TermPattern
. If the match fails, or if no exception is thrown by Expr
, an informative exception will be generated; see the assert
macro for further details. The assertError
, assertExit
, and assertThrow
macros, are equivalent to using assertException
with a ClassPattern
of error
, exit
, or throw
, respectively.
?assertError(badarith, X/0)
?assertExit(normal, exit(normal))
?assertException(throw, {not_found,_}, throw({not_found,42}))
Keep in mind that external commands are highly dependent on the operating system. You can use the standard library function os:type()
in test generator functions, to produce different sets of tests depending on the current operating system.
Note: these macros introduce a run-time dependency on the EUnit library code, if compiled with testing enabled.
assertCmd(CommandString)
Runs CommandString
as an external command, if testing is enabled. Unless the returned status value is 0, an informative exception will be generated. If there is no exception, the result of the macro expression is the atom ok
. If testing is disabled, the macro will not generate any code except the atom ok
, and the command will not be executed.
?assertCmd("mkdir foo")
assertCmdStatus(N, CommandString)
assertCmd(CommandString)
macro, but generates an exception unless the returned status value is
N
.
assertCmdOutput(Text, CommandString)
CommandString
as an external command, if testing is enabled. Unless the output produced by the command exactly matches the specified string
Text
, an informative exception will be generated. (Note that the output is normalized to use a single LF character as line break on all platforms.) If there is no exception, the result of the macro expression is the atom
ok
. If testing is disabled, the macro will not generate any code except the atom
ok
, and the command will not be executed.
cmd(CommandString)
Runs CommandString
as an external command. Unless the returned status value is 0 (indicating success), an informative exception will be generated; otherwise, the result of the macro expression is the output produced by the command, as a flat string. The output is normalized to use a single LF character as line break on all platforms.
This macro is useful in the setup and cleanup sections of fixtures, e.g., for creating and deleting files or perform similar operating system specific tasks, to make sure that the test system is informed of any failures.
A Unix-specific example:{setup, fun () -> ?cmd("mktemp") end, fun (FileName) -> ?cmd("rm " ++ FileName) end, ...}
To help with debugging, EUnit defines several useful macros for printing messages directly to the console (rather than to the standard output). Furthermore, these macros all use the same basic format, which includes the file and line number where they occur, making it possible in some development environments (e.g., when running Erlang in an Emacs buffer) to simply click on the message and jump directly to the corresponding line in the code.
If the macro NODEBUG
is defined before the EUnit header file is included, these macros have no effect; see Compilation control macros for details.
debugHere
ok
.
debugMsg(Text)
Text
(which can be a plain string, an IO-list, or just an atom). The result is always
ok
.
debugFmt(FmtString, Args)
io:format(FmtString, Args)
and outputs it like
debugMsg
. The result is always
ok
.
debugVal(Expr)
Expr
and its current value. E.g.,
?debugVal(f(X))
might be displayed as "
f(X) = 42
". (Large terms are shown truncated.) The result is always the value of
Expr
, so this macro can be wrapped around any expression to display its value when the code is compiled with debugging enabled.
debugTime(Text,Expr)
Text
and the wall clock time for evaluation of
Expr
. The result is always the value of
Expr
, so this macro can be wrapped around any expression to show its run time when the code is compiled with debugging enabled. For example,
List1 = ?debugTime("sorting", lists:sort(List))
might show as "
sorting: 0.015 s
".