TEST_CASE_PERSISTENT_FIXTURE: A new fixture macro for allowing persistent fixtures throughout a TEST_CASE (#2885)

This PR introduces a new `TEST_CASE` macro called `TEST_CASE_PERSISTENT_FIXTURE`. `TEST_CASE_PERSISTENT_FIXTURE` offers the same functionality as `TEST_CASE_METHOD` except for one difference. The object on which the test method is invoked is only created once for all invocations of the test case. The object is created just after the `testCaseStarting` event is broadcast and the object is destroyed just before the `testCaseEnding` event is broadcast.

The main motivation for this new functionality is to allow `TEST_CASE`s to do expensive setup and teardown once per `TEST_CASE`, without having to resort to abusing event listeners or static function variables with manual initialization.


Implements #1602

---------

Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
This commit is contained in:
Keith Stockdale 2024-08-05 16:01:41 +01:00 committed by GitHub
parent 33e24b14fc
commit f7cd0ba051
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 643 additions and 62 deletions

View File

@ -8,6 +8,7 @@
[`CATCH_CONFIG_*` customization options in CMake](#catch_config_-customization-options-in-cmake)<br> [`CATCH_CONFIG_*` customization options in CMake](#catch_config_-customization-options-in-cmake)<br>
[Installing Catch2 from git repository](#installing-catch2-from-git-repository)<br> [Installing Catch2 from git repository](#installing-catch2-from-git-repository)<br>
[Installing Catch2 from vcpkg](#installing-catch2-from-vcpkg)<br> [Installing Catch2 from vcpkg](#installing-catch2-from-vcpkg)<br>
[Installing Catch2 from Bazel](#installing-catch2-from-bazel)<br>
Because we use CMake to build Catch2, we also provide a couple of Because we use CMake to build Catch2, we also provide a couple of
integration points for our users. integration points for our users.

View File

@ -8,6 +8,7 @@
- Assertion: [REQUIRE, CHECK](../examples/030-Asn-Require-Check.cpp) - Assertion: [REQUIRE, CHECK](../examples/030-Asn-Require-Check.cpp)
- Fixture: [Sections](../examples/100-Fix-Section.cpp) - Fixture: [Sections](../examples/100-Fix-Section.cpp)
- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp) - Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
- Fixture: [Persistent fixtures](../examples/111-Fix-PersistentFixture.cpp)
- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp) - BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)
- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp) - Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
- Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp) - Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp)

View File

@ -93,30 +93,6 @@ TEST_CASE("STATIC_CHECK showcase", "[traits]") {
## Test case related macros ## Test case related macros
* `METHOD_AS_TEST_CASE`
`METHOD_AS_TEST_CASE( member-function-pointer, description )` 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.
```cpp
class TestClass {
std::string s;
public:
TestClass()
:s( "hello" )
{}
void testCase() {
REQUIRE( s == "hello" );
}
};
METHOD_AS_TEST_CASE( TestClass::testCase, "Use class's method as a test case", "[class]" )
```
* `REGISTER_TEST_CASE` * `REGISTER_TEST_CASE`
`REGISTER_TEST_CASE( function, description )` let's you register `REGISTER_TEST_CASE( function, description )` let's you register

View File

@ -1,9 +1,30 @@
<a id="top"></a> <a id="top"></a>
# Test fixtures # Test fixtures
## Defining test fixtures **Contents**<br>
[Non-Templated test fixtures](#non-templated-test-fixtures)<br>
[Templated test fixtures](#templated-test-fixtures)<br>
[Signature-based parameterised test fixtures](#signature-based-parametrised-test-fixtures)<br>
[Template fixtures with types specified in template type lists](#template-fixtures-with-types-specified-in-template-type-lists)<br>
Although Catch allows you to group tests together as [sections within a test case](test-cases-and-sections.md), it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure: ## Non-Templated test fixtures
Although Catch2 allows you to group tests together as
[sections within a test case](test-cases-and-sections.md), it can still
be convenient, sometimes, to group them using a more traditional test.
Catch2 fully supports this too with 3 different macros for
non-templated test fixtures. They are:
| Macro | Description |
|----------|-------------|
|1. `TEST_CASE_METHOD(className, ...)`| Creates a uniquely named class which inherits from the class specified by `className`. The test function will be a member of this derived class. An instance of the derived class will be created for every partial run of the test case. |
|2. `METHOD_AS_TEST_CASE(member-function, ...)`| Uses `member-function` as the test function. An instance of the class will be created for each partial run of the test case. |
|3. `TEST_CASE_PERSISTENT_FIXTURE(className, ...)`| Creates a uniquely named class which inherits from the class specified by `className`. The test function will be a member of this derived class. An instance of the derived class will be created at the start of the test run. That instance will be destroyed once the entire test case has ended. |
### 1. `TEST_CASE_METHOD`
You define a `TEST_CASE_METHOD` test fixture as a simple structure:
```c++ ```c++
class UniqueTestsFixture { class UniqueTestsFixture {
@ -30,8 +51,116 @@ class UniqueTestsFixture {
} }
``` ```
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. 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.
### 2. `METHOD_AS_TEST_CASE`
`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.
```cpp
class TestClass {
std::string s;
public:
TestClass()
:s( "hello" )
{}
void testCase() {
REQUIRE( s == "hello" );
}
};
METHOD_AS_TEST_CASE( TestClass::testCase, "Use class's method as a test case", "[class]" )
```
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.
### 3. `TEST_CASE_PERSISTENT_FIXTURE`
> [Introduced](https://github.com/catchorg/Catch2/pull/2885) in Catch2 X.Y.Z
`TEST_CASE_PERSISTENT_FIXTURE` behaves in the same way as
[TEST_CASE_METHOD](#1-test_case_method) except that there will only be
one instance created throughout the entire run of a test case. To
demonstrate this have a look at the following example:
```cpp
class ClassWithExpensiveSetup {
public:
ClassWithExpensiveSetup() {
// expensive construction
std::this_thread::sleep_for( std::chrono::seconds( 2 ) );
}
~ClassWithExpensiveSetup() noexcept {
// expensive destruction
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
}
int getInt() const { return 42; }
};
struct MyFixture {
mutable int myInt = 0;
ClassWithExpensiveSetup expensive;
};
TEST_CASE_PERSISTENT_FIXTURE( MyFixture, "Tests with MyFixture" ) {
const int val = myInt++;
SECTION( "First partial run" ) {
const auto otherValue = expensive.getInt();
REQUIRE( val == 0 );
REQUIRE( otherValue == 42 );
}
SECTION( "Second partial run" ) { REQUIRE( val == 1 ); }
}
```
This example demonstates two possible use-cases of this fixture type:
1. Improve test run times by reducing the amount of expensive and
redundant setup and tear-down required.
2. Reusing results from the previous partial run, in the current
partial run.
This test case will be executed twice as there are two leaf sections.
On the first run `val` will be `0` and on the second run `val` will be
`1`. This demonstrates that we were able to use the results of the
previous partial run in subsequent partial runs.
Additionally, we are simulating an expensive object using
`std::this_thread::sleep_for`, but real world use-cases could be:
1. Creating a D3D12/Vulkan device
2. Connecting to a database
3. Loading a file.
The fixture object (`MyFixture`) will be constructed just before the
test case begins, and it will be destroyed just after the test case
ends. Therefore, this expensive object will only be created and
destroyed once during the execution of this test case. If we had used
`TEST_CASE_METHOD`, `MyFixture` would have been created and destroyed
twice during the execution of this test case.
NOTE: The member function which runs the test case is `const`. Therefore
if you want to mutate any member of the fixture it must be marked as
`mutable` as shown in this example. This is to make it clear that
the initial state of the fixture is intended to mutate during the
execution of the test case.
## Templated test fixtures
Catch2 also provides `TEMPLATE_TEST_CASE_METHOD` and Catch2 also provides `TEMPLATE_TEST_CASE_METHOD` and
`TEMPLATE_PRODUCT_TEST_CASE_METHOD` that can be used together `TEMPLATE_PRODUCT_TEST_CASE_METHOD` that can be used together
@ -93,7 +222,7 @@ _While there is an upper limit on the number of types you can specify
in single `TEMPLATE_TEST_CASE_METHOD` or `TEMPLATE_PRODUCT_TEST_CASE_METHOD`, in single `TEMPLATE_TEST_CASE_METHOD` or `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
the limit is very high and should not be encountered in practice._ the limit is very high and should not be encountered in practice._
## Signature-based parametrised test fixtures ## Signature-based parameterised test fixtures
> [Introduced](https://github.com/catchorg/Catch2/issues/1609) in Catch2 2.8.0. > [Introduced](https://github.com/catchorg/Catch2/issues/1609) in Catch2 2.8.0.

View File

@ -0,0 +1,74 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Fixture.cpp
// Catch2 has three ways to express fixtures:
// - Sections
// - Traditional class-based fixtures that are created and destroyed on every
// partial run
// - Traditional class-based fixtures that are created at the start of a test
// case and destroyed at the end of a test case (this file)
// main() provided by linkage to Catch2WithMain
#include <catch2/catch_test_macros.hpp>
#include <thread>
class ClassWithExpensiveSetup {
public:
ClassWithExpensiveSetup() {
// Imagine some really expensive set up here.
// e.g.
// setting up a D3D12/Vulkan Device,
// connecting to a database,
// loading a file
// etc etc etc
std::this_thread::sleep_for( std::chrono::seconds( 2 ) );
}
~ClassWithExpensiveSetup() noexcept {
// We can do any clean up of the expensive class in the destructor
// e.g.
// destroy D3D12/Vulkan Device,
// disconnecting from a database,
// release file handle
// etc etc etc
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
}
int getInt() const { return 42; }
};
struct MyFixture {
// The test case member function is const.
// Therefore we need to mark any member of the fixture
// that needs to mutate as mutable.
mutable int myInt = 0;
ClassWithExpensiveSetup expensive;
};
// Only one object of type MyFixture will be instantiated for the run
// of this test case even though there are two leaf sections.
// This is useful if your test case requires an object that is
// expensive to create and could be reused for each partial run of the
// test case.
TEST_CASE_PERSISTENT_FIXTURE( MyFixture, "Tests with MyFixture" ) {
const int val = myInt++;
SECTION( "First partial run" ) {
const auto otherValue = expensive.getInt();
REQUIRE( val == 0 );
REQUIRE( otherValue == 42 );
}
SECTION( "Second partial run" ) { REQUIRE( val == 1 ); }
}

View File

@ -28,6 +28,7 @@ set( SOURCES_IDIOMATIC_EXAMPLES
030-Asn-Require-Check.cpp 030-Asn-Require-Check.cpp
100-Fix-Section.cpp 100-Fix-Section.cpp
110-Fix-ClassFixture.cpp 110-Fix-ClassFixture.cpp
111-Fix-PersistentFixture.cpp
120-Bdd-ScenarioGivenWhenThen.cpp 120-Bdd-ScenarioGivenWhenThen.cpp
210-Evt-EventListeners.cpp 210-Evt-EventListeners.cpp
232-Cfg-CustomMain.cpp 232-Cfg-CustomMain.cpp

View File

@ -112,6 +112,14 @@ namespace Catch {
TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) : TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) :
m_info(info), m_invoker(invoker) {} m_info(info), m_invoker(invoker) {}
void prepareTestCase() const {
m_invoker->prepareTestCase();
}
void tearDownTestCase() const {
m_invoker->tearDownTestCase();
}
void invoke() const { void invoke() const {
m_invoker->invoke(); m_invoker->invoke();
} }

View File

@ -43,6 +43,7 @@
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, __VA_ARGS__ )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
@ -97,6 +98,7 @@
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) #define CATCH_METHOD_AS_TEST_CASE( method, ... )
#define CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define CATCH_SECTION( ... ) #define CATCH_SECTION( ... )
#define CATCH_DYNAMIC_SECTION( ... ) #define CATCH_DYNAMIC_SECTION( ... )
@ -142,6 +144,7 @@
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, __VA_ARGS__ )
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
@ -195,6 +198,7 @@
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__)
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
#define METHOD_AS_TEST_CASE( method, ... ) #define METHOD_AS_TEST_CASE( method, ... )
#define TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__)
#define REGISTER_TEST_CASE( Function, ... ) (void)(0) #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define SECTION( ... ) #define SECTION( ... )
#define DYNAMIC_SECTION( ... ) #define DYNAMIC_SECTION( ... )

View File

@ -12,6 +12,8 @@ namespace Catch {
class ITestInvoker { class ITestInvoker {
public: public:
virtual void prepareTestCase();
virtual void tearDownTestCase();
virtual void invoke() const = 0; virtual void invoke() const = 0;
virtual ~ITestInvoker(); // = default virtual ~ITestInvoker(); // = default
}; };

View File

@ -185,6 +185,7 @@ namespace Catch {
auto const& testInfo = testCase.getTestCaseInfo(); auto const& testInfo = testCase.getTestCaseInfo();
m_reporter->testCaseStarting(testInfo); m_reporter->testCaseStarting(testInfo);
testCase.prepareTestCase();
m_activeTestCase = &testCase; m_activeTestCase = &testCase;
@ -254,6 +255,7 @@ namespace Catch {
deltaTotals.testCases.failed++; deltaTotals.testCases.failed++;
} }
m_totals.testCases += deltaTotals.testCases; m_totals.testCases += deltaTotals.testCases;
testCase.tearDownTestCase();
m_reporter->testCaseEnded(TestCaseStats(testInfo, m_reporter->testCaseEnded(TestCaseStats(testInfo,
deltaTotals, deltaTotals,
CATCH_MOVE(redirectedCout), CATCH_MOVE(redirectedCout),

View File

@ -16,6 +16,8 @@
#include <iterator> #include <iterator>
namespace Catch { namespace Catch {
void ITestInvoker::prepareTestCase() {}
void ITestInvoker::tearDownTestCase() {}
ITestInvoker::~ITestInvoker() = default; ITestInvoker::~ITestInvoker() = default;
namespace { namespace {

View File

@ -47,6 +47,33 @@ Detail::unique_ptr<ITestInvoker> makeTestInvoker( void (C::*testAsMethod)() ) {
return Detail::make_unique<TestInvokerAsMethod<C>>( testAsMethod ); return Detail::make_unique<TestInvokerAsMethod<C>>( testAsMethod );
} }
template <typename C>
class TestInvokerFixture : public ITestInvoker {
void ( C::*m_testAsMethod )() const;
Detail::unique_ptr<C> m_fixture = nullptr;
public:
TestInvokerFixture( void ( C::*testAsMethod )() const) noexcept : m_testAsMethod( testAsMethod ) {}
void prepareTestCase() override {
m_fixture = Detail::make_unique<C>();
}
void tearDownTestCase() override {
m_fixture.reset();
}
void invoke() const override {
auto* f = m_fixture.get();
( f->*m_testAsMethod )();
}
};
template<typename C>
Detail::unique_ptr<ITestInvoker> makeTestInvokerFixture( void ( C::*testAsMethod )() const ) {
return Detail::make_unique<TestInvokerFixture<C>>( testAsMethod );
}
struct NameAndTags { struct NameAndTags {
constexpr NameAndTags( StringRef name_ = StringRef(), constexpr NameAndTags( StringRef name_ = StringRef(),
StringRef tags_ = StringRef() ) noexcept: StringRef tags_ = StringRef() ) noexcept:
@ -143,6 +170,26 @@ static int catchInternalSectionHint = 0;
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ ) INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE2( TestName, ClassName, ... ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
namespace { \
struct TestName : INTERNAL_CATCH_REMOVE_PARENS( ClassName ) { \
void test() const; \
}; \
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
Catch::makeTestInvokerFixture( &TestName::test ), \
CATCH_INTERNAL_LINEINFO, \
#ClassName##_catch_sr, \
Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
} \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
void TestName::test() const
#define INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE( ClassName, ... ) \
INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \

View File

@ -11,34 +11,28 @@
* and expressions in assertion macros are not run. * and expressions in assertion macros are not run.
*/ */
#include <catch2/catch_test_macros.hpp>
#include <catch2/benchmark/catch_benchmark.hpp> #include <catch2/benchmark/catch_benchmark.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers.hpp> #include <catch2/matchers/catch_matchers.hpp>
#include <catch2/matchers/catch_matchers_predicate.hpp> #include <catch2/matchers/catch_matchers_predicate.hpp>
#include <iostream> #include <iostream>
struct foo { struct foo {
foo(){ foo() { REQUIRE_NOTHROW( print() ); }
REQUIRE_NOTHROW( print() ); void print() const { std::cout << "This should not happen\n"; }
}
void print() const {
std::cout << "This should not happen\n";
}
}; };
#if defined(__clang__) #if defined( __clang__ )
#pragma clang diagnostic push # pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors" # pragma clang diagnostic ignored "-Wglobal-constructors"
#endif #endif
// Construct foo, but `foo::print` should not be run // Construct foo, but `foo::print` should not be run
static foo f; static foo f;
#if defined( __clang__ )
#if defined(__clang__)
// The test is unused since the registration is disabled // The test is unused since the registration is disabled
#pragma clang diagnostic ignored "-Wunused-function" # pragma clang diagnostic ignored "-Wunused-function"
#endif #endif
// This test should not be run, because it won't be registered // This test should not be run, because it won't be registered
@ -60,6 +54,26 @@ TEST_CASE( "Disabled Macros" ) {
BENCHMARK( "Disabled benchmark" ) { REQUIRE( 1 == 2 ); }; BENCHMARK( "Disabled benchmark" ) { REQUIRE( 1 == 2 ); };
} }
#if defined(__clang__) struct DisabledFixture {};
#pragma clang diagnostic pop
TEST_CASE_PERSISTENT_FIXTURE( DisabledFixture, "Disabled Persistent Fixture" ) {
CHECK( 1 == 2 );
REQUIRE( 1 == 2 );
std::cout << "This should not happen\n";
FAIL();
// Test that static assertions don't fire when macros are disabled
STATIC_CHECK( 0 == 1 );
STATIC_REQUIRE( !true );
CAPTURE( 1 );
CAPTURE( 1, "captured" );
REQUIRE_THAT( 1,
Catch::Matchers::Predicate( []( int ) { return false; } ) );
BENCHMARK( "Disabled benchmark" ) { REQUIRE( 1 == 2 ); };
}
#if defined( __clang__ )
# pragma clang diagnostic pop
#endif #endif

View File

@ -68,6 +68,8 @@ Nor would this
:test-result: PASS A TEMPLATE_TEST_CASE_METHOD_SIG based test run that succeeds - 6 :test-result: PASS A TEMPLATE_TEST_CASE_METHOD_SIG based test run that succeeds - 6
:test-result: FAIL A TEST_CASE_METHOD based test run that fails :test-result: FAIL A TEST_CASE_METHOD based test run that fails
:test-result: PASS A TEST_CASE_METHOD based test run that succeeds :test-result: PASS A TEST_CASE_METHOD based test run that succeeds
:test-result: FAIL A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
:test-result: PASS A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
:test-result: PASS A Template product test case - Foo<float> :test-result: PASS A Template product test case - Foo<float>
:test-result: PASS A Template product test case - Foo<int> :test-result: PASS A Template product test case - Foo<int>
:test-result: PASS A Template product test case - std::vector<float> :test-result: PASS A Template product test case - std::vector<float>

View File

@ -66,6 +66,8 @@
:test-result: PASS A TEMPLATE_TEST_CASE_METHOD_SIG based test run that succeeds - 6 :test-result: PASS A TEMPLATE_TEST_CASE_METHOD_SIG based test run that succeeds - 6
:test-result: FAIL A TEST_CASE_METHOD based test run that fails :test-result: FAIL A TEST_CASE_METHOD based test run that fails
:test-result: PASS A TEST_CASE_METHOD based test run that succeeds :test-result: PASS A TEST_CASE_METHOD based test run that succeeds
:test-result: FAIL A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
:test-result: PASS A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
:test-result: PASS A Template product test case - Foo<float> :test-result: PASS A Template product test case - Foo<float>
:test-result: PASS A Template product test case - Foo<int> :test-result: PASS A Template product test case - Foo<int>
:test-result: PASS A Template product test case - std::vector<float> :test-result: PASS A Template product test case - std::vector<float>

View File

@ -241,6 +241,10 @@ Class.tests.cpp:<line number>: passed: Nttp_Fixture<V>::value > 0 for: 3 > 0
Class.tests.cpp:<line number>: passed: Nttp_Fixture<V>::value > 0 for: 6 > 0 Class.tests.cpp:<line number>: passed: Nttp_Fixture<V>::value > 0 for: 6 > 0
Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2 Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2
Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1 Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1
Class.tests.cpp:<line number>: passed: m_a++ == 0 for: 0 == 0
Class.tests.cpp:<line number>: failed: m_a == 0 for: 1 == 0
Class.tests.cpp:<line number>: passed: m_a++ == 0 for: 0 == 0
Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0 Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0 Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0 Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
@ -2840,7 +2844,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0 InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
test cases: 416 | 311 passed | 85 failed | 6 skipped | 14 failed as expected test cases: 418 | 312 passed | 86 failed | 6 skipped | 14 failed as expected
assertions: 2255 | 2074 passed | 146 failed | 35 failed as expected assertions: 2259 | 2077 passed | 147 failed | 35 failed as expected

View File

@ -239,6 +239,10 @@ Class.tests.cpp:<line number>: passed: Nttp_Fixture<V>::value > 0 for: 3 > 0
Class.tests.cpp:<line number>: passed: Nttp_Fixture<V>::value > 0 for: 6 > 0 Class.tests.cpp:<line number>: passed: Nttp_Fixture<V>::value > 0 for: 6 > 0
Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2 Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2
Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1 Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1
Class.tests.cpp:<line number>: passed: m_a++ == 0 for: 0 == 0
Class.tests.cpp:<line number>: failed: m_a == 0 for: 1 == 0
Class.tests.cpp:<line number>: passed: m_a++ == 0 for: 0 == 0
Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0 Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0 Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0 Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
@ -2829,7 +2833,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0 InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
test cases: 416 | 311 passed | 85 failed | 6 skipped | 14 failed as expected test cases: 418 | 312 passed | 86 failed | 6 skipped | 14 failed as expected
assertions: 2255 | 2074 passed | 146 failed | 35 failed as expected assertions: 2259 | 2077 passed | 147 failed | 35 failed as expected

View File

@ -297,6 +297,18 @@ Class.tests.cpp:<line number>: FAILED:
with expansion: with expansion:
1 == 2 1 == 2
-------------------------------------------------------------------------------
A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
Second partial run
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( m_a == 0 )
with expansion:
1 == 0
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
A couple of nested sections followed by a failure A couple of nested sections followed by a failure
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -1598,6 +1610,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 416 | 325 passed | 70 failed | 7 skipped | 14 failed as expected test cases: 418 | 326 passed | 71 failed | 7 skipped | 14 failed as expected
assertions: 2238 | 2074 passed | 129 failed | 35 failed as expected assertions: 2242 | 2077 passed | 130 failed | 35 failed as expected

View File

@ -2023,6 +2023,54 @@ A TEST_CASE_METHOD based test run that succeeds
Class.tests.cpp:<line number> Class.tests.cpp:<line number>
............................................................................... ...............................................................................
Class.tests.cpp:<line number>: PASSED:
REQUIRE( m_a == 1 )
with expansion:
1 == 1
-------------------------------------------------------------------------------
A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
First partial run
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: PASSED:
REQUIRE( m_a++ == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
Second partial run
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( m_a == 0 )
with expansion:
1 == 0
-------------------------------------------------------------------------------
A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
First partial run
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: PASSED:
REQUIRE( m_a++ == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
Second partial run
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: PASSED: Class.tests.cpp:<line number>: PASSED:
REQUIRE( m_a == 1 ) REQUIRE( m_a == 1 )
with expansion: with expansion:
@ -18894,6 +18942,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 416 | 311 passed | 85 failed | 6 skipped | 14 failed as expected test cases: 418 | 312 passed | 86 failed | 6 skipped | 14 failed as expected
assertions: 2255 | 2074 passed | 146 failed | 35 failed as expected assertions: 2259 | 2077 passed | 147 failed | 35 failed as expected

View File

@ -2021,6 +2021,54 @@ A TEST_CASE_METHOD based test run that succeeds
Class.tests.cpp:<line number> Class.tests.cpp:<line number>
............................................................................... ...............................................................................
Class.tests.cpp:<line number>: PASSED:
REQUIRE( m_a == 1 )
with expansion:
1 == 1
-------------------------------------------------------------------------------
A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
First partial run
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: PASSED:
REQUIRE( m_a++ == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
Second partial run
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: FAILED:
REQUIRE( m_a == 0 )
with expansion:
1 == 0
-------------------------------------------------------------------------------
A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
First partial run
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: PASSED:
REQUIRE( m_a++ == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
Second partial run
-------------------------------------------------------------------------------
Class.tests.cpp:<line number>
...............................................................................
Class.tests.cpp:<line number>: PASSED: Class.tests.cpp:<line number>: PASSED:
REQUIRE( m_a == 1 ) REQUIRE( m_a == 1 )
with expansion: with expansion:
@ -18883,6 +18931,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 416 | 311 passed | 85 failed | 6 skipped | 14 failed as expected test cases: 418 | 312 passed | 86 failed | 6 skipped | 14 failed as expected
assertions: 2255 | 2074 passed | 146 failed | 35 failed as expected assertions: 2259 | 2077 passed | 147 failed | 35 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact <testsuitesloose text artifact
> >
<testsuite name="<exe-name>" errors="17" failures="129" skipped="12" tests="2267" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="130" skipped="12" tests="2271" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties> <properties>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
<property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/> <property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/>
@ -313,6 +313,18 @@ at Class.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}" status="run"/> <testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}" status="run"/>
<testcase classname="<exe-name>.Persistent_Fixture" name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails/First partial run" time="{duration}" status="run"/>
<testcase classname="<exe-name>.Persistent_Fixture" name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails/Second partial run" time="{duration}" status="run">
<failure message="m_a == 0" type="REQUIRE">
FAILED:
REQUIRE( m_a == 0 )
with expansion:
1 == 0
at Class.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.Persistent_Fixture" name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds/First partial run" time="{duration}" status="run"/>
<testcase classname="<exe-name>.Persistent_Fixture" name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds/Second partial run" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;float>" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;float>" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;int>" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;int>" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="A Template product test case - std::vector&lt;float>" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="A Template product test case - std::vector&lt;float>" time="{duration}" status="run"/>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuites> <testsuites>
<testsuite name="<exe-name>" errors="17" failures="129" skipped="12" tests="2267" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="130" skipped="12" tests="2271" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties> <properties>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
<property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/> <property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/>
@ -312,6 +312,18 @@ at Class.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}" status="run"/> <testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}" status="run"/>
<testcase classname="<exe-name>.Persistent_Fixture" name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails/First partial run" time="{duration}" status="run"/>
<testcase classname="<exe-name>.Persistent_Fixture" name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails/Second partial run" time="{duration}" status="run">
<failure message="m_a == 0" type="REQUIRE">
FAILED:
REQUIRE( m_a == 0 )
with expansion:
1 == 0
at Class.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.Persistent_Fixture" name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds/First partial run" time="{duration}" status="run"/>
<testcase classname="<exe-name>.Persistent_Fixture" name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds/Second partial run" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;float>" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;float>" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;int>" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;int>" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="A Template product test case - std::vector&lt;float>" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="A Template product test case - std::vector&lt;float>" time="{duration}" status="run"/>

View File

@ -519,6 +519,18 @@ at Class.tests.cpp:<line number>
</failure> </failure>
</testCase> </testCase>
<testCase name="A TEST_CASE_METHOD based test run that succeeds" duration="{duration}"/> <testCase name="A TEST_CASE_METHOD based test run that succeeds" duration="{duration}"/>
<testCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails/First partial run" duration="{duration}"/>
<testCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails/Second partial run" duration="{duration}">
<failure message="REQUIRE(m_a == 0)">
FAILED:
REQUIRE( m_a == 0 )
with expansion:
1 == 0
at Class.tests.cpp:<line number>
</failure>
</testCase>
<testCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds/First partial run" duration="{duration}"/>
<testCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds/Second partial run" duration="{duration}"/>
<testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 0" duration="{duration}"/> <testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 0" duration="{duration}"/>
<testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 1" duration="{duration}"/> <testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 1" duration="{duration}"/>
<testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 2" duration="{duration}"/> <testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 2" duration="{duration}"/>

View File

@ -518,6 +518,18 @@ at Class.tests.cpp:<line number>
</failure> </failure>
</testCase> </testCase>
<testCase name="A TEST_CASE_METHOD based test run that succeeds" duration="{duration}"/> <testCase name="A TEST_CASE_METHOD based test run that succeeds" duration="{duration}"/>
<testCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails/First partial run" duration="{duration}"/>
<testCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails/Second partial run" duration="{duration}">
<failure message="REQUIRE(m_a == 0)">
FAILED:
REQUIRE( m_a == 0 )
with expansion:
1 == 0
at Class.tests.cpp:<line number>
</failure>
</testCase>
<testCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds/First partial run" duration="{duration}"/>
<testCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds/Second partial run" duration="{duration}"/>
<testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 0" duration="{duration}"/> <testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 0" duration="{duration}"/>
<testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 1" duration="{duration}"/> <testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 1" duration="{duration}"/>
<testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 2" duration="{duration}"/> <testCase name="Template test case method with test types specified inside std::tuple - MyTypes - 2" duration="{duration}"/>

View File

@ -478,6 +478,14 @@ ok {test-number} - Nttp_Fixture<V>::value > 0 for: 6 > 0
not ok {test-number} - m_a == 2 for: 1 == 2 not ok {test-number} - m_a == 2 for: 1 == 2
# A TEST_CASE_METHOD based test run that succeeds # A TEST_CASE_METHOD based test run that succeeds
ok {test-number} - m_a == 1 for: 1 == 1 ok {test-number} - m_a == 1 for: 1 == 1
# A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
ok {test-number} - m_a++ == 0 for: 0 == 0
# A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
not ok {test-number} - m_a == 0 for: 1 == 0
# A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
ok {test-number} - m_a++ == 0 for: 0 == 0
# A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
ok {test-number} - m_a == 1 for: 1 == 1
# A Template product test case - Foo<float> # A Template product test case - Foo<float>
ok {test-number} - x.size() == 0 for: 0 == 0 ok {test-number} - x.size() == 0 for: 0 == 0
# A Template product test case - Foo<int> # A Template product test case - Foo<int>
@ -4539,5 +4547,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} - ok {test-number} -
# xmlentitycheck # xmlentitycheck
ok {test-number} - ok {test-number} -
1..2267 1..2271

View File

@ -476,6 +476,14 @@ ok {test-number} - Nttp_Fixture<V>::value > 0 for: 6 > 0
not ok {test-number} - m_a == 2 for: 1 == 2 not ok {test-number} - m_a == 2 for: 1 == 2
# A TEST_CASE_METHOD based test run that succeeds # A TEST_CASE_METHOD based test run that succeeds
ok {test-number} - m_a == 1 for: 1 == 1 ok {test-number} - m_a == 1 for: 1 == 1
# A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
ok {test-number} - m_a++ == 0 for: 0 == 0
# A TEST_CASE_PERSISTENT_FIXTURE based test run that fails
not ok {test-number} - m_a == 0 for: 1 == 0
# A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
ok {test-number} - m_a++ == 0 for: 0 == 0
# A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds
ok {test-number} - m_a == 1 for: 1 == 1
# A Template product test case - Foo<float> # A Template product test case - Foo<float>
ok {test-number} - x.size() == 0 for: 0 == 0 ok {test-number} - x.size() == 0 for: 0 == 0
# A Template product test case - Foo<int> # A Template product test case - Foo<int>
@ -4528,5 +4536,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} - ok {test-number} -
# xmlentitycheck # xmlentitycheck
ok {test-number} - ok {test-number} -
1..2267 1..2271

View File

@ -166,6 +166,11 @@
##teamcity[testFinished name='A TEST_CASE_METHOD based test run that fails' duration="{duration}"] ##teamcity[testFinished name='A TEST_CASE_METHOD based test run that fails' duration="{duration}"]
##teamcity[testStarted name='A TEST_CASE_METHOD based test run that succeeds'] ##teamcity[testStarted name='A TEST_CASE_METHOD based test run that succeeds']
##teamcity[testFinished name='A TEST_CASE_METHOD based test run that succeeds' duration="{duration}"] ##teamcity[testFinished name='A TEST_CASE_METHOD based test run that succeeds' duration="{duration}"]
##teamcity[testStarted name='A TEST_CASE_PERSISTENT_FIXTURE based test run that fails']
##teamcity[testFailed name='A TEST_CASE_PERSISTENT_FIXTURE based test run that fails' message='-------------------------------------------------------------------------------|nSecond partial run|n-------------------------------------------------------------------------------|nClass.tests.cpp:<line number>|n...............................................................................|n|nClass.tests.cpp:<line number>|nexpression failed|n REQUIRE( m_a == 0 )|nwith expansion:|n 1 == 0|n']
##teamcity[testFinished name='A TEST_CASE_PERSISTENT_FIXTURE based test run that fails' duration="{duration}"]
##teamcity[testStarted name='A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds']
##teamcity[testFinished name='A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds' duration="{duration}"]
##teamcity[testStarted name='A Template product test case - Foo<float>'] ##teamcity[testStarted name='A Template product test case - Foo<float>']
##teamcity[testFinished name='A Template product test case - Foo<float>' duration="{duration}"] ##teamcity[testFinished name='A Template product test case - Foo<float>' duration="{duration}"]
##teamcity[testStarted name='A Template product test case - Foo<int>'] ##teamcity[testStarted name='A Template product test case - Foo<int>']

View File

@ -166,6 +166,11 @@
##teamcity[testFinished name='A TEST_CASE_METHOD based test run that fails' duration="{duration}"] ##teamcity[testFinished name='A TEST_CASE_METHOD based test run that fails' duration="{duration}"]
##teamcity[testStarted name='A TEST_CASE_METHOD based test run that succeeds'] ##teamcity[testStarted name='A TEST_CASE_METHOD based test run that succeeds']
##teamcity[testFinished name='A TEST_CASE_METHOD based test run that succeeds' duration="{duration}"] ##teamcity[testFinished name='A TEST_CASE_METHOD based test run that succeeds' duration="{duration}"]
##teamcity[testStarted name='A TEST_CASE_PERSISTENT_FIXTURE based test run that fails']
##teamcity[testFailed name='A TEST_CASE_PERSISTENT_FIXTURE based test run that fails' message='-------------------------------------------------------------------------------|nSecond partial run|n-------------------------------------------------------------------------------|nClass.tests.cpp:<line number>|n...............................................................................|n|nClass.tests.cpp:<line number>|nexpression failed|n REQUIRE( m_a == 0 )|nwith expansion:|n 1 == 0|n']
##teamcity[testFinished name='A TEST_CASE_PERSISTENT_FIXTURE based test run that fails' duration="{duration}"]
##teamcity[testStarted name='A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds']
##teamcity[testFinished name='A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds' duration="{duration}"]
##teamcity[testStarted name='A Template product test case - Foo<float>'] ##teamcity[testStarted name='A Template product test case - Foo<float>']
##teamcity[testFinished name='A Template product test case - Foo<float>' duration="{duration}"] ##teamcity[testFinished name='A Template product test case - Foo<float>' duration="{duration}"]
##teamcity[testStarted name='A Template product test case - Foo<int>'] ##teamcity[testStarted name='A Template product test case - Foo<int>']

View File

@ -2056,6 +2056,56 @@ Nor would this
</Expression> </Expression>
<OverallResult success="true" skips="0"/> <OverallResult success="true" skips="0"/>
</TestCase> </TestCase>
<TestCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails" tags="[.][class][failing]" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Section name="First partial run" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Original>
m_a++ == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
</Section>
<Section name="Second partial run" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Expression success="false" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Original>
m_a == 0
</Original>
<Expanded>
1 == 0
</Expanded>
</Expression>
<OverallResults successes="0" failures="1" expectedFailures="0" skipped="false"/>
</Section>
<OverallResult success="false" skips="0"/>
</TestCase>
<TestCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds" tags="[class]" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Section name="First partial run" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Original>
m_a++ == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
</Section>
<Section name="Second partial run" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Original>
m_a == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
</Section>
<OverallResult success="true" skips="0"/>
</TestCase>
<TestCase name="A Template product test case - Foo&lt;float>" tags="[product][template]" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" > <TestCase name="A Template product test case - Foo&lt;float>" tags="[product][template]" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" >
<Original> <Original>
@ -21832,6 +21882,6 @@ Approx( -1.95996398454005449 )
</Section> </Section>
<OverallResult success="true" skips="0"/> <OverallResult success="true" skips="0"/>
</TestCase> </TestCase>
<OverallResults successes="2074" failures="146" expectedFailures="35" skips="12"/> <OverallResults successes="2077" failures="147" expectedFailures="35" skips="12"/>
<OverallResultsCases successes="311" failures="85" expectedFailures="14" skips="6"/> <OverallResultsCases successes="312" failures="86" expectedFailures="14" skips="6"/>
</Catch2TestRun> </Catch2TestRun>

View File

@ -2056,6 +2056,56 @@ Nor would this
</Expression> </Expression>
<OverallResult success="true" skips="0"/> <OverallResult success="true" skips="0"/>
</TestCase> </TestCase>
<TestCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that fails" tags="[.][class][failing]" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Section name="First partial run" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Original>
m_a++ == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
</Section>
<Section name="Second partial run" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Expression success="false" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Original>
m_a == 0
</Original>
<Expanded>
1 == 0
</Expanded>
</Expression>
<OverallResults successes="0" failures="1" expectedFailures="0" skipped="false"/>
</Section>
<OverallResult success="false" skips="0"/>
</TestCase>
<TestCase name="A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds" tags="[class]" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Section name="First partial run" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Original>
m_a++ == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
</Section>
<Section name="Second partial run" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Class.tests.cpp" >
<Original>
m_a == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
</Section>
<OverallResult success="true" skips="0"/>
</TestCase>
<TestCase name="A Template product test case - Foo&lt;float>" tags="[product][template]" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" > <TestCase name="A Template product test case - Foo&lt;float>" tags="[product][template]" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" >
<Original> <Original>
@ -21831,6 +21881,6 @@ Approx( -1.95996398454005449 )
</Section> </Section>
<OverallResult success="true" skips="0"/> <OverallResult success="true" skips="0"/>
</TestCase> </TestCase>
<OverallResults successes="2074" failures="146" expectedFailures="35" skips="12"/> <OverallResults successes="2077" failures="147" expectedFailures="35" skips="12"/>
<OverallResultsCases successes="311" failures="85" expectedFailures="14" skips="6"/> <OverallResultsCases successes="312" failures="86" expectedFailures="14" skips="6"/>
</Catch2TestRun> </Catch2TestRun>

View File

@ -32,6 +32,10 @@ namespace {
int m_a; int m_a;
}; };
struct Persistent_Fixture {
mutable int m_a = 0;
};
template <typename T> struct Template_Fixture { template <typename T> struct Template_Fixture {
Template_Fixture(): m_a( 1 ) {} Template_Fixture(): m_a( 1 ) {}
@ -64,6 +68,17 @@ TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that succeeds", "[
REQUIRE( m_a == 1 ); REQUIRE( m_a == 1 );
} }
TEST_CASE_PERSISTENT_FIXTURE( Persistent_Fixture, "A TEST_CASE_PERSISTENT_FIXTURE based test run that succeeds", "[class]" )
{
SECTION( "First partial run" ) {
REQUIRE( m_a++ == 0 );
}
SECTION( "Second partial run" ) {
REQUIRE( m_a == 1 );
}
}
TEMPLATE_TEST_CASE_METHOD(Template_Fixture, "A TEMPLATE_TEST_CASE_METHOD based test run that succeeds", "[class][template]", int, float, double) { TEMPLATE_TEST_CASE_METHOD(Template_Fixture, "A TEMPLATE_TEST_CASE_METHOD based test run that succeeds", "[class][template]", int, float, double) {
REQUIRE( Template_Fixture<TestType>::m_a == 1 ); REQUIRE( Template_Fixture<TestType>::m_a == 1 );
} }
@ -96,6 +111,17 @@ namespace Inner
REQUIRE( m_a == 2 ); REQUIRE( m_a == 2 );
} }
TEST_CASE_PERSISTENT_FIXTURE( Persistent_Fixture, "A TEST_CASE_PERSISTENT_FIXTURE based test run that fails", "[.][class][failing]" )
{
SECTION( "First partial run" ) {
REQUIRE( m_a++ == 0 );
}
SECTION( "Second partial run" ) {
REQUIRE( m_a == 0 );
}
}
TEMPLATE_TEST_CASE_METHOD(Template_Fixture,"A TEMPLATE_TEST_CASE_METHOD based test run that fails", "[.][class][template][failing]", int, float, double) TEMPLATE_TEST_CASE_METHOD(Template_Fixture,"A TEMPLATE_TEST_CASE_METHOD based test run that fails", "[.][class][template][failing]", int, float, double)
{ {
REQUIRE( Template_Fixture<TestType>::m_a == 2 ); REQUIRE( Template_Fixture<TestType>::m_a == 2 );