onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 1 | <!DOCTYPE html> |
| 2 | <html> |
| 3 | <title>assertions</title> |
| 4 | <xmp theme="united" style="display:none;"> |
| 5 | |
| 6 | ## Assertion macros |
| 7 | |
| 8 | Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc). |
| 9 | |
onqtam | d52859a | 2019-03-02 18:28:14 +0200 | [diff] [blame] | 10 | **doctest** is different (but it's like [**Catch**](https://github.com/catchorg/Catch2) in this regard). Because it decomposes comparison 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. |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 11 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 12 | There are 3 levels of assert severity for all assertion macros: |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 13 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 14 | - ```REQUIRE``` - this level will immediately quit the test case if the assert fails and will mark the test case as failed. |
| 15 | - ```CHECK``` - this level will mark the test case as failed if the assert fails but will continue with the test case. |
| 16 | - ```WARN``` - this level will only print a message if the assert fails but will not mark the test case as failed. |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 17 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 18 | The ```CHECK``` level is mostly 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. |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 19 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 20 | All asserts evaluate the expressions only once and if they fail - the values are [**stringified**](stringification.html) properly. |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 21 | |
onqtam | f8d5719 | 2018-08-23 16:02:12 +0300 | [diff] [blame] | 22 | Since **doctest** is [**thread-safe**](faq.html#is-doctest-thread-aware) all asserts and [**logging**](logging.html) macros can be used in threads spawned from test cases. |
| 23 | |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 24 | Note that the ```REQUIRE``` level of asserts uses exceptions to end the current test case. It might be dangerous to use this level of asserts inside destructors of user-defined classes - if a destructor is called during stack unwinding due to an exception and a ```REQUIRE``` assert fails then the program will terminate. Also since C++11 all destructors are by default ```noexcept(true)``` unless specified otherwise so such an assert will lead to ```std::terminate()``` being called. |
| 25 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 26 | ## Expression decomposing asserts |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 27 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 28 | These are of the form ```CHECK(expression)``` (Same for ```REQUIRE``` and ```WARN```). |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 29 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 30 | ```expression``` can be a binary comparison like ```a == b``` or just a single thing like ```vec.isEmpty()```. |
| 31 | |
| 32 | If an exception is thrown it is caught, reported, and counted as a failure (unless the assert is of level ```WARN```). |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 33 | |
| 34 | Examples: |
| 35 | |
| 36 | ``` |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 37 | CHECK(flags == state::alive | state::moving); |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 38 | CHECK(thisReturnsTrue()); |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 39 | REQUIRE(i < 42); |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 40 | ``` |
| 41 | |
onqtam | 72ca33b | 2018-12-05 17:34:33 +0200 | [diff] [blame] | 42 | - Negating asserts - ```<LEVEL>_FALSE(expression)``` - evaluates the expression and records the _logical NOT_ of the result. |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 43 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 44 | These forms exist as a workaround for the fact that ```!``` prefixed expressions cannot be decomposed properly. |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 45 | |
| 46 | Example: |
| 47 | |
| 48 | ``` |
| 49 | REQUIRE_FALSE(thisReturnsFalse()); |
| 50 | ``` |
| 51 | |
onqtam | 72ca33b | 2018-12-05 17:34:33 +0200 | [diff] [blame] | 52 | - Using the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) config option can make compilation of asserts up to [**31-63%**](benchmarks.html#cost-of-an-assertion-macro) faster! |
| 53 | - These asserts also have a ```_MESSAGE``` form - like ```CHECK_MESSAGE(expression, message)``` which is basically a code block ```{}``` with a scoped [**```INFO()```**](logging.html#info) logging macro together with the ```CHECK``` macro - that way the message will be relevant only to that assert. The binary/unary asserts don't have this variation yet. |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 54 | |
| 55 | Examples: |
| 56 | |
| 57 | ``` |
onqtam | 2a069c4 | 2020-12-15 21:02:28 +0200 | [diff] [blame] | 58 | INFO("this is relevant to all asserts, and here is some var: ", local); |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 59 | |
onqtam | 2a069c4 | 2020-12-15 21:02:28 +0200 | [diff] [blame] | 60 | CHECK_MESSAGE(a < b, "relevant only to this assert ", other_local, " more text!"); |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 61 | |
| 62 | CHECK(b < c); // here only the first INFO() will be relevant |
| 63 | ``` |
| 64 | |
onqtam | 2a069c4 | 2020-12-15 21:02:28 +0200 | [diff] [blame] | 65 | For more information about the ```INFO()``` macro visit the [logging page](logging.html). |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 66 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 67 | ## Binary and unary asserts |
| 68 | |
| 69 | These asserts don't use templates to decompose the comparison expressions for the left and right parts. |
| 70 | |
onqtam | 72ca33b | 2018-12-05 17:34:33 +0200 | [diff] [blame] | 71 | These have the same guarantees as the expression decomposing ones but [**57-68% faster**](benchmarks.html#cost-of-an-assertion-macro) for compilation. |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 72 | |
| 73 | ```<LEVEL>``` is one of 3 possible: ```REQUIRE```/```CHECK```/```WARN```. |
| 74 | |
| 75 | - ```<LEVEL>_EQ(left, right)``` - same as ```<LEVEL>(left == right)``` |
| 76 | - ```<LEVEL>_NE(left, right)``` - same as ```<LEVEL>(left != right)``` |
| 77 | - ```<LEVEL>_GT(left, right)``` - same as ```<LEVEL>(left > right)``` |
| 78 | - ```<LEVEL>_LT(left, right)``` - same as ```<LEVEL>(left < right)``` |
| 79 | - ```<LEVEL>_GE(left, right)``` - same as ```<LEVEL>(left >= right)``` |
| 80 | - ```<LEVEL>_LE(left, right)``` - same as ```<LEVEL>(left <= right)``` |
| 81 | - ```<LEVEL>_UNARY(expr)``` - same as ```<LEVEL>(expr)``` |
| 82 | - ```<LEVEL>_UNARY_FALSE(expr)``` - same as ```<LEVEL>_FALSE(expr)``` |
| 83 | |
onqtam | 72ca33b | 2018-12-05 17:34:33 +0200 | [diff] [blame] | 84 | Using the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) config option can make the binary asserts to compile up to [**84-91%**](benchmarks.html#cost-of-an-assertion-macro) faster! |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 85 | |
| 86 | ## Exceptions |
| 87 | |
| 88 | ```<LEVEL>``` is one of 3 possible: ```REQUIRE```/```CHECK```/```WARN```. |
| 89 | |
| 90 | - ```<LEVEL>_THROWS(expression)``` |
| 91 | |
| 92 | Expects that an exception (of any type) is thrown during evaluation of the expression. |
| 93 | |
onqtam | 2d97b85 | 2018-11-30 18:06:17 +0200 | [diff] [blame] | 94 | - ```<LEVEL>_THROWS_AS(expression, exception_type)``` |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 95 | |
| 96 | Expects that an exception of the _specified type_ is thrown during evaluation of the expression. |
| 97 | |
onqtam | 2d97b85 | 2018-11-30 18:06:17 +0200 | [diff] [blame] | 98 | Note that ```const``` and ```&``` are added to the exception type if missing (users shouldn't care) - the standard practice for exceptions in C++ is ```Throw by value, catch by (const) reference```. |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 99 | |
| 100 | ``` |
onqtam | 2d97b85 | 2018-11-30 18:06:17 +0200 | [diff] [blame] | 101 | CHECK_THROWS_AS(func(), const std::exception&); |
| 102 | CHECK_THROWS_AS(func(), std::exception); // same as above |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 103 | ``` |
| 104 | |
onqtam | 2d97b85 | 2018-11-30 18:06:17 +0200 | [diff] [blame] | 105 | - ```<LEVEL>_THROWS_WITH(expression, c_string)``` |
| 106 | |
| 107 | Expects that an exception is thrown during evaluation of the expression and is successfully translated to the _specified c string_ (see [**translating exceptions**](stringification.html#translating-exceptions)). |
| 108 | |
| 109 | ``` |
| 110 | CHECK_THROWS_WITH(func(), "invalid operation!"); |
| 111 | ``` |
| 112 | |
onqtam | 77af200 | 2019-09-22 21:17:20 +0300 | [diff] [blame] | 113 | - ```<LEVEL>_THROWS_WITH_AS(expression, c_string, exception_type)``` |
| 114 | |
| 115 | This is a combination of ```<LEVEL>_THROWS_WITH``` and ```<LEVEL>_THROWS_AS```. |
| 116 | |
| 117 | ``` |
| 118 | CHECK_THROWS_WITH_AS(func(), "invalid operation!", std::runtime_error); |
| 119 | ``` |
| 120 | |
onqtam | 2d97b85 | 2018-11-30 18:06:17 +0200 | [diff] [blame] | 121 | - ```<LEVEL>_NOTHROW(expression)``` |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 122 | |
| 123 | Expects that no exception is thrown during evaluation of the expression. |
| 124 | |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 125 | Note that these asserts also have a ```_MESSAGE``` form - like ```CHECK_THROWS_MESSAGE(expression, message)``` - these work identically to the ```_MESSAGE``` form of the normal macros (```CHECK_MESSAGE(a < b, "this shouldn't fail")```) described earlier. |
| 126 | |
onqtam | 505b05c | 2019-05-06 11:39:02 +0300 | [diff] [blame] | 127 | One may use the [**```DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS```**](configuration.html#doctest_config_void_cast_expressions) config identifier to cast the expression in these asserts to void to avoid warnings or other issues - for example nodiscard statements whose result isn't checked. This will however limit the ability to write entire ```{}``` blocks of code as the expression (or multiple statements) but in that case a simple lambda can be used. This should have been the default behavior from day 1 of the framework... |
| 128 | |
onqtam | f8d5719 | 2018-08-23 16:02:12 +0300 | [diff] [blame] | 129 | ## Using asserts out of a testing context |
| 130 | |
| 131 | Asserts can be used outside of a testing context (in code not called from a ```TEST_CASE()```) instead of [```assert()```](https://en.cppreference.com/w/cpp/error/assert). |
| 132 | |
| 133 | A ```doctest::Context``` object still has to be created somewhere and set as the default one using the ```setAsDefaultForAssertsOutOfTestCases()``` method - and then asserts will work. A handler can be registered by calling the ```setAssertHandler()``` method on the context object. If no handler is set then ```std::abort()``` is called on failure. |
| 134 | |
onqtam | 72ca33b | 2018-12-05 17:34:33 +0200 | [diff] [blame] | 135 | The results would be best when using the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) config identifier. |
onqtam | f8d5719 | 2018-08-23 16:02:12 +0300 | [diff] [blame] | 136 | |
| 137 | Checkout the [**example**](../../examples/all_features/asserts_used_outside_of_tests.cpp) showcasing how that is done. For more information see the [**issue for the feature request**](https://github.com/onqtam/doctest/issues/114). |
| 138 | |
| 139 | Currently [**logging macros**](logging.html) cannot be used for extra context for asserts outside of a test run. That means that the ```_MESSAGE``` variants of asserts are also not usable - since they are just a packed ```INFO()``` with an assert right after it. |
| 140 | |
onqtam | 1435c01 | 2016-09-21 15:29:11 +0300 | [diff] [blame] | 141 | ## Floating point comparisons |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 142 | |
| 143 | When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations. |
| 144 | |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 145 | **doctest** provides a way to perform tolerant comparisons of floating point values through the use of a wrapper class called ```doctest::Approx```. ```doctest::Approx``` can be used on either side of a comparison expression. It overloads the comparisons operators to take a relative tolerance into account. Here's a simple example: |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 146 | |
| 147 | ``` |
| 148 | REQUIRE(performComputation() == doctest::Approx(2.1)); |
| 149 | ``` |
| 150 | |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 151 | By default a small epsilon value (relative - in percentages) is used that covers many simple cases of rounding errors. When this is insufficient the epsilon value (the amount within which a difference either way is ignored) can be specified by calling the ```epsilon()``` method on the ```doctest::Approx``` instance. e.g.: |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 152 | |
| 153 | ``` |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 154 | REQUIRE(22.0/7 == doctest::Approx(3.141).epsilon(0.01)); // allow for a 1% error |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 155 | ``` |
| 156 | |
| 157 | When dealing with very large or very small numbers it can be useful to specify a scale, which can be achieved by calling the ```scale()``` method on the ```doctest::Approx``` instance. |
| 158 | |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 159 | -------- |
| 160 | |
onqtam | b8220c5 | 2017-05-16 00:21:15 +0300 | [diff] [blame] | 161 | - Check out the [**example**](../../examples/all_features/assertion_macros.cpp) which shows many of these macros |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 162 | - Do not wrap assertion macros in ```try```/```catch``` - the REQUIRE macros throw exceptions to end the test case execution! |
| 163 | |
| 164 | --------------- |
| 165 | |
| 166 | [Home](readme.html#reference) |
| 167 | |
onqtam | f8d5719 | 2018-08-23 16:02:12 +0300 | [diff] [blame] | 168 | <p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p> |
| 169 | |
onqtam | 8126b56 | 2016-05-27 17:01:15 +0300 | [diff] [blame] | 170 | |
| 171 | </xmp> |
| 172 | <script src="strapdown.js/strapdown.js"></script> |
| 173 | </html> |