catch2/docs/assertions.md

206 lines
7.2 KiB
Markdown
Raw Normal View History

2017-08-24 15:21:36 +02:00
<a id="top"></a>
2013-06-10 09:18:26 +02:00
# Assertion Macros
**Contents**<br>
[Natural Expressions](#natural-expressions)<br>
[Floating point comparisons](#floating-point-comparisons)<br>
[Exceptions](#exceptions)<br>
[Matcher expressions](#matcher-expressions)<br>
[Thread Safety](#thread-safety)<br>
[Expressions with commas](#expressions-with-commas)<br>
2017-08-28 22:42:26 +02:00
2013-10-02 09:17:46 +02:00
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
2013-06-10 09:18:26 +02:00
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.
2013-06-10 09:18:26 +02:00
Most of these macros come in two forms:
## Natural Expressions
2022-10-05 05:50:40 +02:00
```cpp
#include <catch2/catch_test_macros.hpp>
```
2013-06-10 09:18:26 +02:00
2013-10-02 09:17:46 +02:00
The ```REQUIRE``` family of macros tests an expression and aborts the test case if it fails.
2014-06-11 09:17:17 +02:00
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.
2013-10-02 09:17:46 +02:00
2022-10-17 15:02:45 +02:00
* **REQUIRE(** _expression_ **)** and
2013-10-02 09:17:46 +02:00
* **CHECK(** _expression_ **)**
2013-06-10 09:18:26 +02:00
2017-12-09 21:29:39 +01:00
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.
2013-06-10 09:18:26 +02:00
Examples:
```
2013-06-10 09:18:26 +02:00
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:
* **REQUIRE_FALSE(** _expression_ **)** and
2013-10-02 09:17:46 +02:00
* **CHECK_FALSE(** _expression_ **)**
Note that there is no reason to use these forms for plain bool variables,
because there is no added value in decomposing them.
2013-06-10 09:18:26 +02:00
Example:
```cpp
Status ret = someFunction();
REQUIRE_FALSE(ret); // ret must evaluate to false, and Catch2 will print
// out the value of ret if possibly
```
### Floating point comparisons
2022-10-05 05:50:40 +02:00
```cpp
#include <catch2/catch_approx.hpp>
```
### Other limitations
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.
2017-02-27 14:22:17 +01:00
1) Enclose it in parentheses. Parentheses force evaluation of the expression
before the expression decomposition can touch it, and thus it cannot
be used.
2018-07-15 17:38:57 +02:00
2) 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](#matcher-expressions).
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.
2017-02-27 14:22:17 +01:00
## Floating point comparisons
Comparing floating point numbers is complex, and [so it has its own
documentation page](comparing-floating-point-numbers.md#top).
2017-02-27 14:22:17 +01:00
2013-06-10 09:18:26 +02:00
## Exceptions
2022-10-17 15:02:45 +02:00
* **REQUIRE_NOTHROW(** _expression_ **)** and
* **CHECK_NOTHROW(** _expression_ **)**
Expects that no exception is thrown during evaluation of the expression.
2022-10-17 15:02:45 +02:00
* **REQUIRE_THROWS(** _expression_ **)** and
2013-10-02 09:17:46 +02:00
* **CHECK_THROWS(** _expression_ **)**
2013-06-10 09:18:26 +02:00
Expects that an exception (of any type) is be thrown during evaluation of the expression.
2022-10-17 15:02:45 +02:00
* **REQUIRE_THROWS_AS(** _expression_, _exception type_ **)** and
2013-10-02 09:17:46 +02:00
* **CHECK_THROWS_AS(** _expression_, _exception type_ **)**
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.
2013-06-10 09:18:26 +02:00
2022-10-17 15:02:45 +02:00
* **REQUIRE_THROWS_WITH(** _expression_, _string or string matcher_ **)** and
* **CHECK_THROWS_WITH(** _expression_, _string or string matcher_ **)**
2022-10-05 05:50:40 +02:00
```cpp
#include <catch2/matchers/catch_matchers.hpp>
```
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.
```cpp
REQUIRE_THROWS_WITH( openThePodBayDoors(), Contains( "afraid" ) && Contains( "can't do that" ) );
REQUIRE_THROWS_WITH( dismantleHal(), "My mind is going" );
```
2013-06-10 09:18:26 +02:00
* **REQUIRE_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)** and
* **CHECK_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)**
Expects that exception of _exception type_ is thrown and it matches provided matcher (see the [documentation for Matchers](matchers.md#top)).
_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._
```cpp
REQUIRE_NOTHROW([&](){
int i = 1;
int j = 2;
auto k = i + j;
if (k == 3) {
throw 1;
}
}());
```
2017-06-05 18:42:04 +02:00
2013-06-10 09:18:26 +02:00
## Matcher expressions
To support Matchers a slightly different form is used. Matchers have [their own documentation](matchers.md#top).
2013-06-10 09:18:26 +02:00
2022-10-17 15:02:45 +02:00
* **REQUIRE_THAT(** _lhs_, _matcher expression_ **)** and
* **CHECK_THAT(** _lhs_, _matcher expression_ **)**
Matchers can be composed using `&&`, `||` and `!` operators.
## Thread Safety
Currently assertions in Catch are not thread safe.
For more details, along with workarounds, see the section on [the limitations page](limitations.md#thread-safe-assertions).
## Expressions with commas
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);`
2018-06-01 00:21:14 +02:00
will fail to compile, because the preprocessor sees 3 arguments provided,
but the macro accepts only 2. There are two possible workarounds.
1) Use typedef:
```cpp
using int_pair = std::pair<int, int>;
REQUIRE_THROWS_AS(int_pair(1, 2), std::invalid_argument);
```
This solution is always applicable, but makes the meaning of the code
less clear.
2) Parenthesize the expression:
```cpp
TEST_CASE_METHOD((Fixture<int, int>), "foo", "[bar]") {
SUCCEED();
}
```
This solution is not always applicable, because it might require extra
changes on the Catch's side to work.
2022-10-05 05:50:40 +02:00
## Lambdas
Lambdas are a C++ language feature and can be freely used inside a `TEST_CASE` or a `SECTION`.
```cpp
#include <catch2/catch_test_macros.hpp>
TEST_CASE("Dumb") {
auto fnTest = [](const bool bPass) { CHECK(bPass); };
fnTest(true);
}
```
[godbolt](https://catch2.godbolt.org/z/ebdr9vKcj)
---
[Home](Readme.md#top)