Add --list-listeners option

This commit is contained in:
Martin Hořeňovský 2022-05-10 20:00:36 +02:00
parent ae475a3c19
commit 5a49285e9c
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
33 changed files with 220 additions and 18 deletions

View File

@ -59,6 +59,7 @@ Click one of the following links to take you straight to that option - or scroll
<a href="#listing-available-tests-tags-or-reporters"> ` --list-tests`</a><br />
<a href="#listing-available-tests-tags-or-reporters"> ` --list-tags`</a><br />
<a href="#listing-available-tests-tags-or-reporters"> ` --list-reporters`</a><br />
<a href="#listing-available-tests-tags-or-reporters"> ` --list-listeners`</a><br />
<a href="#order"> ` --order`</a><br />
<a href="#rng-seed"> ` --rng-seed`</a><br />
<a href="#libidentify"> ` --libidentify`</a><br />
@ -200,10 +201,13 @@ Sometimes this results in a flood of failure messages and you'd rather just see
--list-tests
--list-tags
--list-reporters
--list-listeners
```
> The `--list*` options became customizable through reporters in Catch2 X.Y.Z
> The `--list-listeners` option was added in Catch2 X.Y.Z
`--list-tests` lists all registered tests matching specified test spec.
Usually this listing also includes tags, and potentially also other
information, like source location, based on verbosity and reporter's design.
@ -214,6 +218,8 @@ similar information.
`--list-reporters` lists all available reporters and their descriptions.
`--list-listeners` lists all registered listeners and their descriptions.
<a id="sending-output-to-a-file"></a>
## Sending output to a file

View File

@ -192,6 +192,7 @@ v3 releases.
* Added a support for Bazel integration with `XML_OUTPUT_FILE` env var (#2399)
* This has to be enabled during compilation.
* Added `--skip-benchmarks` flag to run tests without any `BENCHMARK`s (#2392, #2408)
* Added option to list all listeners in the binary via `--list-listeners`
### Fixes

View File

@ -111,6 +111,7 @@ namespace Catch {
bool Config::listTests() const { return m_data.listTests; }
bool Config::listTags() const { return m_data.listTags; }
bool Config::listReporters() const { return m_data.listReporters; }
bool Config::listListeners() const { return m_data.listListeners; }
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }

View File

@ -48,6 +48,7 @@ namespace Catch {
bool listTests = false;
bool listTags = false;
bool listReporters = false;
bool listListeners = false;
bool showSuccessfulTests = false;
bool shouldDebugBreak = false;
@ -99,6 +100,7 @@ namespace Catch {
bool listTests() const;
bool listTags() const;
bool listReporters() const;
bool listListeners() const;
std::vector<ReporterSpec> const& getReporterSpecs() const;
std::vector<ProcessedReporterSpec> const&

View File

@ -27,6 +27,7 @@
namespace Catch {
struct ReporterDescription;
struct ListenerDescription;
struct TagInfo;
struct TestCaseInfo;
class TestCaseHandle;
@ -249,11 +250,12 @@ namespace Catch {
//! Writes out information about provided reporters using reporter-specific format
virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0;
//! Writes out the provided listeners descriptions using reporter-specific format
virtual void listListeners(std::vector<ListenerDescription> const& descriptions) = 0;
//! Writes out information about provided tests using reporter-specific format
virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0;
//! Writes out information about the provided tags using reporter-specific format
virtual void listTags(std::vector<TagInfo> const& tags) = 0;
};
using IEventListenerPtr = Detail::unique_ptr<IEventListener>;

View File

@ -9,6 +9,7 @@
#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
#include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <string>
@ -34,6 +35,9 @@ namespace Catch {
public:
virtual ~EventListenerFactory(); // = default
virtual IEventListenerPtr create( IConfig const* config ) const = 0;
//! Return a meaningful name for the listener, e.g. its type name
virtual StringRef getName() const = 0;
//! Return listener's description if available
virtual std::string getDescription() const = 0;
};
} // namespace Catch

View File

@ -280,7 +280,10 @@ namespace Catch {
( "list all/matching tags" )
| Opt( config.listReporters )
["--list-reporters"]
( "list all reporters" )
( "list all available reporters" )
| Opt( config.listListeners )
["--list-listeners"]
( "list all listeners" )
| Opt( setTestOrder, "decl|lex|rand" )
["--order"]
( "test case order (defaults to decl)" )

View File

@ -63,6 +63,19 @@ namespace Catch {
reporter.listReporters(descriptions);
}
void listListeners(IEventListener& reporter) {
std::vector<ListenerDescription> descriptions;
auto const& factories =
getRegistryHub().getReporterRegistry().getListeners();
descriptions.reserve( factories.size() );
for ( auto const& fac : factories ) {
descriptions.push_back( { fac->getName(), fac->getDescription() } );
}
reporter.listListeners( descriptions );
}
} // end anonymous namespace
void TagInfo::add( StringRef spelling ) {
@ -100,6 +113,10 @@ namespace Catch {
listed = true;
listReporters(reporter);
}
if ( config.listListeners() ) {
listed = true;
listListeners( reporter );
}
return listed;
}

View File

@ -23,6 +23,10 @@ namespace Catch {
struct ReporterDescription {
std::string name, description;
};
struct ListenerDescription {
StringRef name;
std::string description;
};
struct TagInfo {
void add(StringRef spelling);

View File

@ -152,6 +152,33 @@ namespace Catch {
out << '\n' << std::flush;
}
void defaultListListeners( std::ostream& out,
std::vector<ListenerDescription> const& descriptions ) {
const auto maxNameLen =
std::max_element( descriptions.begin(),
descriptions.end(),
[]( ListenerDescription const& lhs,
ListenerDescription const& rhs ) {
return lhs.name.size() < rhs.name.size();
} )
->name.size();
out << "Registered listeners:\n";
for ( auto const& desc : descriptions ) {
out << TextFlow::Column( static_cast<std::string>( desc.name ) +
':' )
.indent( 2 )
.width( maxNameLen + 5 ) +
TextFlow::Column( desc.description )
.initialIndent( 0 )
.indent( 2 )
.width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
<< '\n';
}
out << '\n' << std::flush;
}
void defaultListTags( std::ostream& out,
std::vector<TagInfo> const& tags,
bool isFiltered ) {
@ -233,6 +260,8 @@ namespace Catch {
void EventListenerBase::assertionEnded( AssertionStats const& ) {}
void EventListenerBase::listReporters(
std::vector<ReporterDescription> const& ) {}
void EventListenerBase::listListeners(
std::vector<ListenerDescription> const& ) {}
void EventListenerBase::listTests( std::vector<TestCaseHandle> const& ) {}
void EventListenerBase::listTags( std::vector<TagInfo> const& ) {}
void EventListenerBase::noMatchingTestCases( StringRef ) {}

View File

@ -29,6 +29,11 @@ namespace Catch {
defaultListReporters(m_stream, descriptions, m_config->verbosity());
}
void ReporterBase::listListeners(
std::vector<ListenerDescription> const& descriptions ) {
defaultListListeners( m_stream, descriptions );
}
void ReporterBase::listTests(std::vector<TestCaseHandle> const& tests) {
defaultListTests(m_stream,
m_colour.get(),

View File

@ -50,6 +50,14 @@ namespace Catch {
*/
void listReporters(
std::vector<ReporterDescription> const& descriptions ) override;
/**
* Provides a simple default listing of listeners
*
* Looks similarly to listing of reporters, but with listener type
* instead of reporter name.
*/
void listListeners(
std::vector<ListenerDescription> const& descriptions ) override;
/**
* Provides a simple default listing of tests.
*

View File

@ -36,6 +36,8 @@ namespace Catch {
void listReporters(
std::vector<ReporterDescription> const& descriptions ) override;
void listListeners(
std::vector<ListenerDescription> const& descriptions ) override;
void listTests( std::vector<TestCaseHandle> const& tests ) override;
void listTags( std::vector<TagInfo> const& tagInfos ) override;

View File

@ -49,6 +49,13 @@ namespace Catch {
std::vector<ReporterDescription> const& descriptions,
Verbosity verbosity );
/**
* Lists listeners descriptions to the provided stream in user-friendly
* format
*/
void defaultListListeners( std::ostream& out,
std::vector<ListenerDescription> const& descriptions );
/**
* Lists tag information to the provided stream in user-friendly format
*

View File

@ -176,6 +176,13 @@ namespace Catch {
}
}
void MultiReporter::listListeners(
std::vector<ListenerDescription> const& descriptions ) {
for ( auto& reporterish : m_reporterLikes ) {
reporterish->listListeners( descriptions );
}
}
void MultiReporter::listTests(std::vector<TestCaseHandle> const& tests) {
for (auto& reporterish : m_reporterLikes) {
reporterish->listTests(tests);

View File

@ -60,6 +60,7 @@ namespace Catch {
void skipTest( TestCaseInfo const& testInfo ) override;
void listReporters(std::vector<ReporterDescription> const& descriptions) override;
void listListeners(std::vector<ListenerDescription> const& descriptions) override;
void listTests(std::vector<TestCaseHandle> const& tests) override;
void listTags(std::vector<TagInfo> const& tags) override;

View File

@ -59,33 +59,36 @@ namespace Catch {
class ListenerRegistrar {
class TypedListenerFactory : public EventListenerFactory {
StringRef m_defaultDescription;
StringRef m_listenerName;
std::string getDescriptionImpl( std::true_type ) const {
return T::getDescription();
}
std::string getDescriptionImpl( std::false_type ) const {
return static_cast<std::string>(m_defaultDescription);
return "(No description provided)";
}
public:
TypedListenerFactory( StringRef defaultDescription ):
m_defaultDescription( defaultDescription ) {}
TypedListenerFactory( StringRef listenerName ):
m_listenerName( listenerName ) {}
IEventListenerPtr create( IConfig const* config ) const override {
return Detail::make_unique<T>( config );
}
StringRef getName() const override {
return m_listenerName;
}
std::string getDescription() const override {
return getDescriptionImpl( Detail::has_description<T>{} );
}
};
public:
ListenerRegistrar(StringRef defaultDescription) {
getMutableRegistryHub().registerListener( Detail::make_unique<TypedListenerFactory>(defaultDescription) );
ListenerRegistrar(StringRef listenerName) {
getMutableRegistryHub().registerListener( Detail::make_unique<TypedListenerFactory>(listenerName) );
}
};
}

View File

@ -207,6 +207,18 @@ set_tests_properties(List::Reporters::XmlOutput PROPERTIES
FAIL_REGULAR_EXPRESSION "Available reporters:"
)
add_test(NAME List::Listeners::Output
COMMAND
$<TARGET_FILE:SelfTest> --list-listeners
)
set_tests_properties(List::Listeners::Output
PROPERTIES
PASS_REGULAR_EXPRESSION "Registered listeners:"
)
add_test(NAME List::Listeners::ExitCode
COMMAND
$<TARGET_FILE:SelfTest> --list-listeners
)
add_test(NAME NoAssertions COMMAND $<TARGET_FILE:SelfTest> -w NoAssertions "An empty test with no assertions")

View File

@ -1898,6 +1898,10 @@ Reporters.tests.cpp:<line number>: passed: listingString, ContainsSubstring( "fa
1 test case
" ( contains: "fake test name" and contains: "fakeTestTag" )
Reporters.tests.cpp:<line number>: passed: listingString, ContainsSubstring( "fakeListener"s ) && ContainsSubstring( "fake description"s ) for: "Registered listeners:
fakeListener: fake description
" ( contains: "fakeListener" and contains: "fake description" )
Misc.tests.cpp:<line number>: passed: with 1 message: 'oops!'
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'For some reason someone is throwing a string literal!'
PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true

View File

@ -1891,6 +1891,10 @@ Reporters.tests.cpp:<line number>: passed: listingString, ContainsSubstring( "fa
1 test case
" ( contains: "fake test name" and contains: "fakeTestTag" )
Reporters.tests.cpp:<line number>: passed: listingString, ContainsSubstring( "fakeListener"s ) && ContainsSubstring( "fake description"s ) for: "Registered listeners:
fakeListener: fake description
" ( contains: "fakeListener" and contains: "fake description" )
Misc.tests.cpp:<line number>: passed: with 1 message: 'oops!'
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'For some reason someone is throwing a string literal!'
PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true

View File

@ -1395,5 +1395,5 @@ due to unexpected exception with message:
===============================================================================
test cases: 391 | 315 passed | 69 failed | 7 failed as expected
assertions: 2226 | 2071 passed | 128 failed | 27 failed as expected
assertions: 2227 | 2072 passed | 128 failed | 27 failed as expected

View File

@ -13444,6 +13444,21 @@ with expansion:
" ( contains: "fake test name" and contains: "fakeTestTag" )
-------------------------------------------------------------------------------
The default listing implementation write to provided stream
Listing listeners
-------------------------------------------------------------------------------
Reporters.tests.cpp:<line number>
...............................................................................
Reporters.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( listingString, ContainsSubstring( "fakeListener"s ) && ContainsSubstring( "fake description"s ) )
with expansion:
"Registered listeners:
fakeListener: fake description
" ( contains: "fakeListener" and contains: "fake description" )
-------------------------------------------------------------------------------
This test 'should' fail but doesn't
-------------------------------------------------------------------------------
@ -17935,5 +17950,5 @@ Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 391 | 301 passed | 83 failed | 7 failed as expected
assertions: 2241 | 2071 passed | 143 failed | 27 failed as expected
assertions: 2242 | 2072 passed | 143 failed | 27 failed as expected

View File

@ -13437,6 +13437,21 @@ with expansion:
" ( contains: "fake test name" and contains: "fakeTestTag" )
-------------------------------------------------------------------------------
The default listing implementation write to provided stream
Listing listeners
-------------------------------------------------------------------------------
Reporters.tests.cpp:<line number>
...............................................................................
Reporters.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( listingString, ContainsSubstring( "fakeListener"s ) && ContainsSubstring( "fake description"s ) )
with expansion:
"Registered listeners:
fakeListener: fake description
" ( contains: "fakeListener" and contains: "fake description" )
-------------------------------------------------------------------------------
This test 'should' fail but doesn't
-------------------------------------------------------------------------------
@ -17927,5 +17942,5 @@ Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 391 | 301 passed | 83 failed | 7 failed as expected
assertions: 2241 | 2071 passed | 143 failed | 27 failed as expected
assertions: 2242 | 2072 passed | 143 failed | 27 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="126" tests="2241" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="126" tests="2242" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="random-seed" value="1"/>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
@ -1379,6 +1379,7 @@ Misc.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="The default listing implementation write to provided stream/Listing tags" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="The default listing implementation write to provided stream/Listing reporters" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="The default listing implementation write to provided stream/Listing tests" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="The default listing implementation write to provided stream/Listing listeners" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="This test 'should' fail but doesn't" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Thrown string literals are translated" time="{duration}" status="run">
<error type="TEST_CASE">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="<exe-name>" errors="17" failures="126" tests="2241" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="126" tests="2242" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="random-seed" value="1"/>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
@ -1378,6 +1378,7 @@ Misc.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="The default listing implementation write to provided stream/Listing tags" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="The default listing implementation write to provided stream/Listing reporters" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="The default listing implementation write to provided stream/Listing tests" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="The default listing implementation write to provided stream/Listing listeners" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="This test 'should' fail but doesn't" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Thrown string literals are translated" time="{duration}" status="run">
<error type="TEST_CASE">

View File

@ -220,6 +220,7 @@
<testCase name="The default listing implementation write to provided stream/Listing tags" duration="{duration}"/>
<testCase name="The default listing implementation write to provided stream/Listing reporters" duration="{duration}"/>
<testCase name="The default listing implementation write to provided stream/Listing tests" duration="{duration}"/>
<testCase name="The default listing implementation write to provided stream/Listing listeners" duration="{duration}"/>
</file>
<file path="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp">
<testCase name="Cout stream properly declares it writes to stdout" duration="{duration}"/>

View File

@ -219,6 +219,7 @@
<testCase name="The default listing implementation write to provided stream/Listing tags" duration="{duration}"/>
<testCase name="The default listing implementation write to provided stream/Listing reporters" duration="{duration}"/>
<testCase name="The default listing implementation write to provided stream/Listing tests" duration="{duration}"/>
<testCase name="The default listing implementation write to provided stream/Listing listeners" duration="{duration}"/>
</file>
<file path="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp">
<testCase name="Cout stream properly declares it writes to stdout" duration="{duration}"/>

View File

@ -3338,6 +3338,8 @@ ok {test-number} - listingString, ContainsSubstring("[fakeTag]"s) for: "All avai
ok {test-number} - listingString, ContainsSubstring( "fake reporter"s ) && ContainsSubstring( "fake description"s ) for: "Available reporters: fake reporter: fake description " ( contains: "fake reporter" and contains: "fake description" )
# The default listing implementation write to provided stream
ok {test-number} - listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s ) for: "All available test cases: fake test name [fakeTestTag] 1 test case " ( contains: "fake test name" and contains: "fakeTestTag" )
# The default listing implementation write to provided stream
ok {test-number} - listingString, ContainsSubstring( "fakeListener"s ) && ContainsSubstring( "fake description"s ) for: "Registered listeners: fakeListener: fake description " ( contains: "fakeListener" and contains: "fake description" )
# This test 'should' fail but doesn't
ok {test-number} - with 1 message: 'oops!'
# Thrown string literals are translated
@ -4485,5 +4487,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} -
# xmlentitycheck
ok {test-number} -
1..2241
1..2242

View File

@ -3331,6 +3331,8 @@ ok {test-number} - listingString, ContainsSubstring("[fakeTag]"s) for: "All avai
ok {test-number} - listingString, ContainsSubstring( "fake reporter"s ) && ContainsSubstring( "fake description"s ) for: "Available reporters: fake reporter: fake description " ( contains: "fake reporter" and contains: "fake description" )
# The default listing implementation write to provided stream
ok {test-number} - listingString, ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fakeTestTag"s ) for: "All available test cases: fake test name [fakeTestTag] 1 test case " ( contains: "fake test name" and contains: "fakeTestTag" )
# The default listing implementation write to provided stream
ok {test-number} - listingString, ContainsSubstring( "fakeListener"s ) && ContainsSubstring( "fake description"s ) for: "Registered listeners: fakeListener: fake description " ( contains: "fakeListener" and contains: "fake description" )
# This test 'should' fail but doesn't
ok {test-number} - with 1 message: 'oops!'
# Thrown string literals are translated
@ -4477,5 +4479,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} -
# xmlentitycheck
ok {test-number} -
1..2241
1..2242

View File

@ -15754,6 +15754,20 @@ Message from section two
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Listing listeners" filename="tests/<exe-name>/IntrospectiveTests/Reporters.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/IntrospectiveTests/Reporters.tests.cpp" >
<Original>
listingString, ContainsSubstring( "fakeListener"s ) &amp;&amp; ContainsSubstring( "fake description"s )
</Original>
<Expanded>
"Registered listeners:
fakeListener: fake description
" ( contains: "fakeListener" and contains: "fake description" )
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="This test 'should' fail but doesn't" tags="[!shouldfail][.][failing]" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" >
@ -21061,6 +21075,6 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="2071" failures="143" expectedFailures="27"/>
<OverallResults successes="2072" failures="143" expectedFailures="27"/>
<OverallResultsCases successes="301" failures="83" expectedFailures="7"/>
</Catch2TestRun>

View File

@ -15754,6 +15754,20 @@ Message from section two
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Listing listeners" filename="tests/<exe-name>/IntrospectiveTests/Reporters.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/IntrospectiveTests/Reporters.tests.cpp" >
<Original>
listingString, ContainsSubstring( "fakeListener"s ) &amp;&amp; ContainsSubstring( "fake description"s )
</Original>
<Expanded>
"Registered listeners:
fakeListener: fake description
" ( contains: "fakeListener" and contains: "fake description" )
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="This test 'should' fail but doesn't" tags="[!shouldfail][.][failing]" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" >
@ -21060,6 +21074,6 @@ There is no extra whitespace here
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="2071" failures="143" expectedFailures="27"/>
<OverallResults successes="2072" failures="143" expectedFailures="27"/>
<OverallResultsCases successes="301" failures="83" expectedFailures="7"/>
</Catch2TestRun>

View File

@ -84,6 +84,16 @@ TEST_CASE( "The default listing implementation write to provided stream",
ContainsSubstring( "fake test name"s ) &&
ContainsSubstring( "fakeTestTag"s ) );
}
SECTION( "Listing listeners" ) {
std::vector<Catch::ListenerDescription> listeners(
{ { "fakeListener"_catch_sr, "fake description" } } );
Catch::defaultListListeners( sstream.stream(), listeners );
auto listingString = sstream.str();
REQUIRE_THAT( listingString,
ContainsSubstring( "fakeListener"s ) &&
ContainsSubstring( "fake description"s ) );
}
}
TEST_CASE( "Reporter's write listings to provided stream", "[reporters]" ) {

View File

@ -48,6 +48,10 @@ class ValidatingTestListener : public Catch::EventListenerBase {
};
public:
static std::string getDescription() {
return "Validates ordering of Catch2's listener events";
}
ValidatingTestListener(Catch::IConfig const* config) :
EventListenerBase(config) {
m_preferences.shouldReportAllAssertions = true;