Skip to content

Commit 39a4b82

Browse files
committed
Rename the example file
Fix the license on the file Improve the example to make the use cases much clearer. Also fix up the documentation
1 parent bf4575a commit 39a4b82

File tree

4 files changed

+137
-52
lines changed

4 files changed

+137
-52
lines changed

docs/test-fixtures.md

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,18 @@ class UniqueTestsFixture {
5151
}
5252
```
5353
54-
The two test cases here will create uniquely-named derived classes of UniqueTestsFixture and thus can access the `getID()` protected method and `conn` member variables. This ensures that both the test cases are able to create a DBConnection using the same method (DRY principle) and that any ID's created are unique such that the order that tests are executed does not matter.
54+
The two test cases here will create uniquely-named derived classes of
55+
UniqueTestsFixture and thus can access the `getID()` protected method
56+
and `conn` member variables. This ensures that both the test cases
57+
are able to create a DBConnection using the same method
58+
(DRY principle) and that any ID's created are unique such that the
59+
order that tests are executed does not matter.
5560
5661
### 2. `METHOD_AS_TEST_CASE`
5762
58-
`METHOD_AS_TEST_CASE` lets you register a member function of a class as a Catch2 test case. The class will be separately instantiated for each method registered in this way.
63+
`METHOD_AS_TEST_CASE` lets you register a member function of a class
64+
as a Catch2 test case. The class will be separately instantiated
65+
for each method registered in this way.
5966
6067
```cpp
6168
class TestClass {
@@ -75,40 +82,78 @@ public:
7582
METHOD_AS_TEST_CASE( TestClass::testCase, "Use class's method as a test case", "[class]" )
7683
```
7784

78-
This type of fixture is similar to [TEST_CASE_METHOD](#1-test_case_method) except in this case it will directly use the provided class to create an object rather than a derived class.
85+
This type of fixture is similar to [TEST_CASE_METHOD](#1-test_case_method) except in this
86+
case it will directly use the provided class to create an object rather than a derived
87+
class.
7988

8089
### 3. `TEST_CASE_PERSISTENT_FIXTURE`
8190

82-
> [Introduced](link-to-issue-or-PR) in Catch2 X.Y.Z
91+
> [Introduced](https://github.com/catchorg/Catch2/pull/2885) in Catch2 X.Y.Z
8392

8493
`TEST_CASE_PERSISTENT_FIXTURE` behaves in the same way as
8594
[TEST_CASE_METHOD](#1-test_case_method) except that there will only be
8695
one instance created throughout the entire run of a test case. To
8796
demonstrate this have a look at the following example:
8897

8998
```cpp
90-
struct MyFixture{
91-
int MyInt = 0;
99+
class ClassWithExpensiveSetup {
100+
public:
101+
ClassWithExpensiveSetup() {
102+
// expensive construction
103+
std::this_thread::sleep_for( std::chrono::seconds( 2 ) );
104+
}
105+
106+
~ClassWithExpensiveSetup() noexcept {
107+
// expensive destruction
108+
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
109+
}
110+
111+
int getInt() const { return 42; }
92112
};
93113

94-
TEST_CASE_PERSISTENT_FIXTURE(MyFixture, "Tests with MyFixture") {
95-
96-
const int val = MyInt++;
114+
struct MyFixture {
115+
mutable int myInt = 0;
116+
ClassWithExpensiveSetup expensive;
117+
};
97118

98-
SECTION("First partial run") {
99-
REQUIRE(val == 0);
100-
}
119+
TEST_CASE_PERSISTENT_FIXTURE( MyFixture, "Tests with MyFixture" ) {
120+
121+
const int val = myInt++;
101122

102-
SECTION("Second partial run") {
103-
REQUIRE(val == 1);
123+
SECTION( "First partial run" ) {
124+
const auto otherValue = expensive.getInt();
125+
REQUIRE( val == 0 );
126+
REQUIRE( otherValue == 42 );
104127
}
128+
129+
SECTION( "Second partial run" ) { REQUIRE( val == 1 ); }
105130
}
106131
```
132+
133+
This example demonstates two possible use-cases of this fixture type:
134+
1. Improve test run times by reducing the amount of expensive and
135+
redundant setup and tear-down required.
136+
2. Reusing results from the previous partial run, in the current
137+
partial run.
138+
107139
This test case will be executed twice as there are two leaf sections.
108140
On the first run `val` will be `0` and on the second run `val` will be
109-
`1`. This is useful if you would like to share some expensive setup code
110-
with all runs of your test case which can't be done at static
111-
initialization time.
141+
`1`.
142+
143+
Additionally, we are simulating an expensive object using
144+
`std::this_thread::sleep_for`, but real world use-cases could be:
145+
1. Creating a D3D12/Vulkan device
146+
2. Connecting to a database
147+
3. Loading a file.
148+
149+
The fixture object will be constructed just before the test case begins, and
150+
it will be destroyed just after the test case ends.
151+
152+
NOTE: The member function which runs the test case is `const`. Therefore
153+
if you want to mutate any member of the fixture it must be marked as
154+
`mutable` as shown in this example. This is to make it clear that
155+
the initial state of the fixture is intended to mutate during the
156+
execution of the test case.
112157
113158
## Templated test fixtures
114159
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
2+
// Copyright Catch2 Authors
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// (See accompanying file LICENSE.txt or copy at
5+
// https://www.boost.org/LICENSE_1_0.txt)
6+
7+
// SPDX-License-Identifier: BSL-1.0
8+
9+
// Fixture.cpp
10+
11+
// Catch has three ways to express fixtures:
12+
// - Sections
13+
// - Traditional class-based fixtures that are created and destroyed on every
14+
// partial run
15+
// - Traditional class-based fixtures that are created at the start of a test
16+
// case and destroyed at the end of a test case (this file)
17+
18+
// main() provided by linkage to Catch2WithMain
19+
20+
#include <catch2/catch_test_macros.hpp>
21+
22+
#include <thread>
23+
24+
class ClassWithExpensiveSetup {
25+
public:
26+
ClassWithExpensiveSetup() {
27+
// Imagine some really expensive set up here.
28+
// e.g.
29+
// setting up a D3D12/Vulkan Device,
30+
// connecting to a database,
31+
// loading a file
32+
// etc etc etc
33+
std::this_thread::sleep_for( std::chrono::seconds( 2 ) );
34+
}
35+
36+
~ClassWithExpensiveSetup() noexcept {
37+
// We can do any clean up of the expensive class in the destructor
38+
// e.g.
39+
// destroy D3D12/Vulkan Device,
40+
// disconnecting from a database,
41+
// release file handle
42+
// etc etc etc
43+
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
44+
}
45+
46+
int getInt() const { return 42; }
47+
};
48+
49+
struct MyFixture {
50+
51+
// The test case member function is const.
52+
// Therefore we need to mark any member of the fixture
53+
// that needs to mutate as mutable.
54+
mutable int myInt = 0;
55+
ClassWithExpensiveSetup expensive;
56+
};
57+
58+
// Only one object of type MyFixture will be instantiated for the run
59+
// of this test case even though there are two leaf sections.
60+
// This is useful if your test case requires an object that is
61+
// expensive to create and could be reused for each partial run of the
62+
// test case.
63+
TEST_CASE_PERSISTENT_FIXTURE( MyFixture, "Tests with MyFixture" ) {
64+
65+
const int val = myInt++;
66+
67+
SECTION( "First partial run" ) {
68+
const auto otherValue = expensive.getInt();
69+
REQUIRE( val == 0 );
70+
REQUIRE( otherValue == 42 );
71+
}
72+
73+
SECTION( "Second partial run" ) { REQUIRE( val == 1 ); }
74+
}

examples/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ target_compile_definitions(231-Cfg_OutputStreams PUBLIC CATCH_CONFIG_NOSTDOUT)
2525

2626
# These examples use the standard separate compilation
2727
set( SOURCES_IDIOMATIC_EXAMPLES
28-
Fixture.cpp
2928
030-Asn-Require-Check.cpp
3029
100-Fix-Section.cpp
3130
110-Fix-ClassFixture.cpp
31+
111-Fix-PersistentFixture.cpp
3232
120-Bdd-ScenarioGivenWhenThen.cpp
3333
210-Evt-EventListeners.cpp
3434
232-Cfg-CustomMain.cpp

examples/Fixture.cpp

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)