Contents
Natural
Expressions
Floating point
comparisons
Exceptions
Matcher expressions
Thread Safety
Expressions with commas
Most test frameworks have a large collection of assertion macros to
capture all possible conditional forms (_EQUALS
,
_NOTEQUALS
, _GREATER_THAN
etc).
Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there is a rich set of auxiliary macros as well. We’ll describe all of these here.
Most of these macros come in two forms:
The REQUIRE
family of macros tests an expression and
aborts the test case if it fails. The CHECK
family are
equivalent but execution continues in the same test case even if the
assertion fails. This is useful if you have a series of essentially
orthogonal assertions and it is useful to see all the results rather
than stopping at the first failure.
Evaluates the expression and records the result. If an exception is thrown, it is caught, reported, and counted as a failure. These are the macros you will use most of the time.
Examples:
CHECK( str == "string value" );
CHECK( thisReturnsTrue() );
REQUIRE( i == 42 );
Expressions prefixed with !
cannot be decomposed. If you
have a type that is convertible to bool and you want to assert that it
evaluates to false, use the two forms below:
Note that there is no reason to use these forms for plain bool variables, because there is no added value in decomposing them.
Example:
= someFunction();
Status ret (ret); // ret must evaluate to false, and Catch2 will print
REQUIRE_FALSE// out the value of ret if possibly
Note that expressions containing either of the binary logical
operators, &&
or ||
, cannot be
decomposed and will not compile. The reason behind this is that it is
impossible to overload &&
and ||
in a
way that keeps their short-circuiting semantics, and expression
decomposition relies on overloaded operators to work.
Simple example of an issue with overloading binary logical operators
is a common pointer idiom, p && p->foo == 2
.
Using the built-in &&
operator, p
is
only dereferenced if it is not null. With overloaded
&&
, p
is always dereferenced, thus
causing a segfault if p == nullptr
.
If you want to test expression that contains &&
or ||
, you have two options.
Enclose it in parentheses. Parentheses force evaluation of the expression before the expression decomposition can touch it, and thus it cannot be used.
Rewrite the expression.
REQUIRE(a == 1 && b == 2)
can always be split into
REQUIRE(a == 1); REQUIRE(b == 2);
. Alternatively, if this
is a common pattern in your tests, think about using Matchers. instead. There is no simple
rewrite rule for ||
, but I generally believe that if you
have ||
in your test expression, you should rethink your
tests.
Comparing floating point numbers is complex, and so it has its own documentation page.
Expects that no exception is thrown during evaluation of the expression.
Expects that an exception (of any type) is be thrown during evaluation of the expression.
Expects that an exception of the specified type is thrown
during evaluation of the expression. Note that the exception
type is extended with const&
and you should not
include it yourself.
Expects that an exception is thrown that, when converted to a string, matches the string or string matcher provided (see next section for Matchers).
e.g.
( openThePodBayDoors(), ContainsSubstring( "afraid" ) && ContainsSubstring( "can't do that" ) );
REQUIRE_THROWS_WITH( dismantleHal(), "My mind is going" ); REQUIRE_THROWS_WITH
Expects that exception of exception type is thrown and it matches provided matcher (see the documentation for Matchers).
Please note that the THROW
family of assertions
expects to be passed a single expression, not a statement or series of
statements. If you want to check a more complicated sequence of
operations, you can use a C++11 lambda function.
([&](){
REQUIRE_NOTHROWint i = 1;
int j = 2;
auto k = i + j;
if (k == 3) {
throw 1;
}
}());
To support Matchers a slightly different form is used. Matchers have their own documentation.
Matchers can be composed using &&
,
||
and !
operators.
Currently assertions in Catch are not thread safe. For more details, along with workarounds, see the section on the limitations page.
Because the preprocessor parses code using different rules than the
compiler, multiple-argument assertions
(e.g. REQUIRE_THROWS_AS
) have problems with commas inside
the provided expressions. As an example
REQUIRE_THROWS_AS(std::pair<int, int>(1, 2), std::invalid_argument);
will fail to compile, because the preprocessor sees 3 arguments
provided, but the macro accepts only 2. There are two possible
workarounds.
using int_pair = std::pair<int, int>;
(int_pair(1, 2), std::invalid_argument); REQUIRE_THROWS_AS
This solution is always applicable, but makes the meaning of the code less clear.
((Fixture<int, int>), "foo", "[bar]") {
TEST_CASE_METHOD();
SUCCEED}
This solution is not always applicable, because it might require extra changes on the Catch’s side to work.