2017-08-24 15:21:36 +02:00
|
|
|
<a id="top"></a>
|
2017-08-24 22:21:54 +02:00
|
|
|
# Tutorial
|
|
|
|
|
2017-10-13 11:14:37 +02:00
|
|
|
**Contents**<br>
|
2017-11-03 14:05:09 +01:00
|
|
|
[Getting Catch2](#getting-catch2)<br>
|
2017-10-13 11:14:37 +02:00
|
|
|
[Writing tests](#writing-tests)<br>
|
|
|
|
[Test cases and sections](#test-cases-and-sections)<br>
|
2021-11-16 23:23:29 +01:00
|
|
|
[BDD style testing](#bdd-style-testing)<br>
|
|
|
|
[Data and Type driven tests](#data-and-type-driven-tests)<br>
|
2017-10-13 11:14:37 +02:00
|
|
|
[Next steps](#next-steps)<br>
|
2017-08-28 22:42:26 +02:00
|
|
|
|
2020-10-21 19:59:59 +02:00
|
|
|
|
2021-08-03 13:41:03 +02:00
|
|
|
## Getting Catch2
|
2020-10-21 19:59:59 +02:00
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
Ideally you should be using Catch2 through its [CMake
|
|
|
|
integration](cmake-integration.md#top). Catch2 also provides pkg-config
|
|
|
|
files and two file (header + cpp) distribution, but this documentation
|
|
|
|
will assume you are using CMake. If you are using the two file
|
|
|
|
distribution instead, remember to replace the included header with
|
|
|
|
`catch_amalgamated.hpp`.
|
2013-06-03 21:03:07 +02:00
|
|
|
|
2018-06-21 23:34:17 +02:00
|
|
|
|
2017-08-24 22:21:54 +02:00
|
|
|
## Writing tests
|
2013-06-03 21:03:07 +02:00
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
Let's start with a really simple example
|
|
|
|
([code](../examples/010-TestCase.cpp)). Say you have written a function
|
|
|
|
to calculate factorials and now you want to test it (let's leave aside
|
|
|
|
TDD for now).
|
2013-06-03 21:03:07 +02:00
|
|
|
|
|
|
|
```c++
|
|
|
|
unsigned int Factorial( unsigned int number ) {
|
|
|
|
return number <= 1 ? number : Factorial(number-1)*number;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
```c++
|
2021-08-03 13:41:03 +02:00
|
|
|
#include <catch2/catch_test_macros.hpp>
|
2013-06-03 21:03:07 +02:00
|
|
|
|
|
|
|
unsigned int Factorial( unsigned int number ) {
|
|
|
|
return number <= 1 ? number : Factorial(number-1)*number;
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE( "Factorials are computed", "[factorial]" ) {
|
|
|
|
REQUIRE( Factorial(1) == 1 );
|
|
|
|
REQUIRE( Factorial(2) == 2 );
|
|
|
|
REQUIRE( Factorial(3) == 6 );
|
|
|
|
REQUIRE( Factorial(10) == 3628800 );
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
This will compile to a complete executable which responds to [command
|
|
|
|
line arguments](command-line.md#top). If you just run it with no
|
|
|
|
arguments it will execute all test cases (in this case there is just
|
|
|
|
one), report any failures, report a summary of how many tests passed and
|
|
|
|
failed and return the number of failed tests (useful for if you just
|
|
|
|
want a yes/ no answer to: "did it work").
|
2013-06-03 21:03:07 +02:00
|
|
|
|
2021-08-03 13:41:03 +02:00
|
|
|
Anyway, as the tests above as written will pass, but there is a bug.
|
|
|
|
The problem is that `Factorial(0)` should return 1 (due to [its
|
|
|
|
definition](https://en.wikipedia.org/wiki/Factorial#Factorial_of_zero)).
|
|
|
|
Let's add that as an assertion to the test case:
|
2013-06-03 21:03:07 +02:00
|
|
|
|
|
|
|
```c++
|
|
|
|
TEST_CASE( "Factorials are computed", "[factorial]" ) {
|
|
|
|
REQUIRE( Factorial(0) == 1 );
|
|
|
|
REQUIRE( Factorial(1) == 1 );
|
|
|
|
REQUIRE( Factorial(2) == 2 );
|
|
|
|
REQUIRE( Factorial(3) == 6 );
|
|
|
|
REQUIRE( Factorial(10) == 3628800 );
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
After another compile & run cycle, we will see a test failure. The
|
|
|
|
output will look something like:
|
2013-06-03 21:03:07 +02:00
|
|
|
|
|
|
|
```
|
|
|
|
Example.cpp:9: FAILED:
|
|
|
|
REQUIRE( Factorial(0) == 1 )
|
|
|
|
with expansion:
|
|
|
|
0 == 1
|
|
|
|
```
|
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
Note that the output contains both the original expression, `REQUIRE(
|
|
|
|
Factorial(0) == 1 )` and the actual value returned by the call to the
|
|
|
|
`Factorial` function: `0`.
|
2013-06-03 21:03:07 +02:00
|
|
|
|
2021-08-03 13:41:03 +02:00
|
|
|
We can fix this bug by slightly modifying the `Factorial` function to:
|
2023-07-17 19:00:58 +02:00
|
|
|
|
2013-06-03 21:03:07 +02:00
|
|
|
```c++
|
|
|
|
unsigned int Factorial( unsigned int number ) {
|
|
|
|
return number > 1 ? Factorial(number-1)*number : 1;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
|
2017-08-24 22:21:54 +02:00
|
|
|
### What did we do here?
|
2013-06-03 21:03:07 +02:00
|
|
|
|
2021-08-03 13:41:03 +02:00
|
|
|
Although this was a simple test it's been enough to demonstrate a few
|
2023-07-17 19:00:58 +02:00
|
|
|
things about how Catch2 is used. Let's take a moment to consider those
|
2021-08-03 13:41:03 +02:00
|
|
|
before we move on.
|
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
* We introduce test cases with the `TEST_CASE` macro. This macro takes
|
2021-08-03 13:41:03 +02:00
|
|
|
one or two string arguments - a free form test name and, optionally,
|
2023-07-17 19:00:58 +02:00
|
|
|
one or more tags (for more see [Test cases and
|
|
|
|
Sections](#test-cases-and-sections)).
|
2021-08-03 13:41:03 +02:00
|
|
|
* The test automatically self-registers with the test runner, and user
|
2023-07-17 19:00:58 +02:00
|
|
|
does not have do anything more to ensure that it is picked up by the
|
|
|
|
test framework. _Note that you can run specific test, or set of
|
|
|
|
tests, through the [command line](command-line.md#top)._
|
2021-08-03 13:41:03 +02:00
|
|
|
* The individual test assertions are written using the `REQUIRE` macro.
|
|
|
|
It accepts a boolean expression, and uses expression templates to
|
2023-07-17 19:00:58 +02:00
|
|
|
internally decompose it, so that it can be individually stringified on
|
|
|
|
test failure.
|
2022-10-17 15:02:45 +02:00
|
|
|
|
2021-08-03 13:41:03 +02:00
|
|
|
On the last point, note that there are more testing macros available,
|
|
|
|
because not all useful checks can be expressed as a simple boolean
|
2023-07-17 19:00:58 +02:00
|
|
|
expression. As an example, checking that an expression throws an
|
|
|
|
exception is done with the `REQUIRE_THROWS` macro. More on that later.
|
2013-06-03 21:03:07 +02:00
|
|
|
|
|
|
|
|
2013-10-01 09:20:08 +02:00
|
|
|
## Test cases and sections
|
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
Like most test frameworks, Catch2 supports a class-based fixture
|
|
|
|
mechanism, where individual tests are methods on class and
|
|
|
|
setup/teardown can be done in constructor/destructor of the type.
|
2013-10-01 09:20:08 +02:00
|
|
|
|
2021-11-16 23:23:29 +01:00
|
|
|
However, their use in Catch2 is rare, because idiomatic Catch2 tests
|
2023-07-17 19:00:58 +02:00
|
|
|
instead use _sections_ to share setup and teardown code between test
|
|
|
|
code. This is best explained through an example
|
|
|
|
([code](../examples/100-Fix-Section.cpp)):
|
2013-10-01 09:20:08 +02:00
|
|
|
|
|
|
|
```c++
|
|
|
|
TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
|
|
|
|
|
|
|
|
std::vector<int> v( 5 );
|
2018-11-16 19:39:42 +01:00
|
|
|
|
2013-10-01 09:20:08 +02:00
|
|
|
REQUIRE( v.size() == 5 );
|
|
|
|
REQUIRE( v.capacity() >= 5 );
|
2018-11-16 19:39:42 +01:00
|
|
|
|
2013-10-01 09:20:08 +02:00
|
|
|
SECTION( "resizing bigger changes size and capacity" ) {
|
|
|
|
v.resize( 10 );
|
2018-11-16 19:39:42 +01:00
|
|
|
|
2013-10-01 09:20:08 +02:00
|
|
|
REQUIRE( v.size() == 10 );
|
|
|
|
REQUIRE( v.capacity() >= 10 );
|
|
|
|
}
|
|
|
|
SECTION( "resizing smaller changes size but not capacity" ) {
|
|
|
|
v.resize( 0 );
|
2018-11-16 19:39:42 +01:00
|
|
|
|
2013-10-01 09:20:08 +02:00
|
|
|
REQUIRE( v.size() == 0 );
|
|
|
|
REQUIRE( v.capacity() >= 5 );
|
|
|
|
}
|
|
|
|
SECTION( "reserving bigger changes capacity but not size" ) {
|
|
|
|
v.reserve( 10 );
|
2018-11-16 19:39:42 +01:00
|
|
|
|
2013-10-01 09:20:08 +02:00
|
|
|
REQUIRE( v.size() == 5 );
|
|
|
|
REQUIRE( v.capacity() >= 10 );
|
|
|
|
}
|
|
|
|
SECTION( "reserving smaller does not change size or capacity" ) {
|
|
|
|
v.reserve( 0 );
|
2018-11-16 19:39:42 +01:00
|
|
|
|
2013-10-01 09:20:08 +02:00
|
|
|
REQUIRE( v.size() == 5 );
|
|
|
|
REQUIRE( v.capacity() >= 5 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
For each `SECTION` the `TEST_CASE` is executed from the start. This
|
|
|
|
means that each section is entered with a freshly constructed vector
|
|
|
|
`v`, that we know has size 5 and capacity at least 5, because the two
|
|
|
|
assertions are also checked before the section is entered. Each run
|
|
|
|
through a test case will execute one, and only one, leaf section.
|
2013-10-01 09:20:08 +02:00
|
|
|
|
2021-08-03 13:41:03 +02:00
|
|
|
Section can also be nested, in which case the parent section can be
|
2023-07-17 19:00:58 +02:00
|
|
|
entered multiple times, once for each leaf section. Nested sections are
|
2021-08-03 13:41:03 +02:00
|
|
|
most useful when you have multiple tests that share part of the set up.
|
|
|
|
To continue on the vector example above, you could add a check that
|
2023-07-17 19:00:58 +02:00
|
|
|
`std::vector::reserve` does not remove unused excess capacity, like
|
|
|
|
this:
|
2013-10-01 09:20:08 +02:00
|
|
|
|
2021-08-03 13:41:03 +02:00
|
|
|
```cpp
|
2013-11-14 20:08:19 +01:00
|
|
|
SECTION( "reserving bigger changes capacity but not size" ) {
|
|
|
|
v.reserve( 10 );
|
2018-11-16 19:39:42 +01:00
|
|
|
|
2013-11-14 20:08:19 +01:00
|
|
|
REQUIRE( v.size() == 5 );
|
|
|
|
REQUIRE( v.capacity() >= 10 );
|
2021-08-03 13:41:03 +02:00
|
|
|
SECTION( "reserving down unused capacity does not change capacity" ) {
|
2013-11-14 20:08:19 +01:00
|
|
|
v.reserve( 7 );
|
2021-08-03 13:41:03 +02:00
|
|
|
REQUIRE( v.size() == 5 );
|
2013-11-14 20:08:19 +01:00
|
|
|
REQUIRE( v.capacity() >= 10 );
|
|
|
|
}
|
|
|
|
}
|
2014-03-06 01:46:20 +01:00
|
|
|
```
|
2013-11-14 20:08:19 +01:00
|
|
|
|
2022-10-17 15:02:45 +02:00
|
|
|
Another way to look at sections is that they are a way to define a tree
|
2023-07-17 19:00:58 +02:00
|
|
|
of paths through the test. Each section represents a node, and the
|
|
|
|
final tree is walked in depth-first manner, with each path only visiting
|
|
|
|
only one leaf node.
|
2021-08-03 13:41:03 +02:00
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
There is no practical limit on nesting sections, as long as your
|
|
|
|
compiler can handle them, but keep in mind that overly nested sections
|
|
|
|
can become unreadable. From experience, having section nest more than 3
|
|
|
|
levels is usually very hard to follow and not worth the removed
|
|
|
|
duplication.
|
2021-08-03 13:41:03 +02:00
|
|
|
|
2013-11-14 20:08:19 +01:00
|
|
|
|
2021-11-16 23:23:29 +01:00
|
|
|
## BDD style testing
|
2013-11-14 20:08:19 +01:00
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
Catch2 also provides some basic support for BDD-style testing. There
|
|
|
|
are macro aliases for `TEST_CASE` and `SECTIONS` that you can use so
|
|
|
|
that the resulting tests read as BDD spec. `SCENARIO` acts as a
|
|
|
|
`TEST_CASE` with "Scenario: " name prefix. Then there are `GIVEN`,
|
|
|
|
`WHEN`, `THEN` (and their variants with `AND_` prefix), which act as a
|
|
|
|
`SECTION`, similarly prefixed with the macro name.
|
2013-11-14 20:08:19 +01:00
|
|
|
|
2021-11-16 23:23:29 +01:00
|
|
|
For more details on the macros look at the [test cases and
|
2023-07-17 19:00:58 +02:00
|
|
|
sections](test-cases-and-sections.md#top) part of the reference docs, or
|
|
|
|
at the [vector example done with BDD
|
|
|
|
macros](../examples/120-Bdd-ScenarioGivenWhenThen.cpp).
|
2013-10-01 09:20:08 +02:00
|
|
|
|
2015-05-18 19:40:58 +02:00
|
|
|
|
2021-11-16 23:23:29 +01:00
|
|
|
## Data and Type driven tests
|
2018-11-16 19:39:42 +01:00
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
Test cases in Catch2 can also be driven by types, input data, or both at
|
|
|
|
the same time.
|
2018-11-16 19:39:42 +01:00
|
|
|
|
2023-07-17 19:00:58 +02:00
|
|
|
For more details look into the Catch2 reference, either at the [type
|
|
|
|
parametrized test
|
|
|
|
cases](test-cases-and-sections.md#type-parametrised-test-cases), or
|
|
|
|
[data generators](generators.md#top).
|
2018-11-16 19:39:42 +01:00
|
|
|
|
|
|
|
|
2013-06-03 21:03:07 +02:00
|
|
|
## Next steps
|
2013-06-07 20:09:38 +02:00
|
|
|
|
2021-11-16 23:23:29 +01:00
|
|
|
This page is a brief introduction to get you up and running with Catch2,
|
2023-07-17 19:00:58 +02:00
|
|
|
and to show the basic features of Catch2. The features mentioned here
|
|
|
|
can get you quite far, but there are many more. However, you can read
|
|
|
|
about these as you go, in the ever-growing [reference
|
|
|
|
section](Readme.md#top) of the documentation.
|
2014-12-15 08:25:54 +01:00
|
|
|
|
2013-06-07 20:09:38 +02:00
|
|
|
|
|
|
|
---
|
|
|
|
|
2017-08-24 15:33:38 +02:00
|
|
|
[Home](Readme.md#top)
|