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-tests`</a><br />
<a href="#listing-available-tests-tags-or-reporters"> ` --list-tags`</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-reporters`</a><br />
<a href="#listing-available-tests-tags-or-reporters"> ` --list-listeners`</a><br />
<a href="#order"> ` --order`</a><br /> <a href="#order"> ` --order`</a><br />
<a href="#rng-seed"> ` --rng-seed`</a><br /> <a href="#rng-seed"> ` --rng-seed`</a><br />
<a href="#libidentify"> ` --libidentify`</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-tests
--list-tags --list-tags
--list-reporters --list-reporters
--list-listeners
``` ```
> The `--list*` options became customizable through reporters in Catch2 X.Y.Z > 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. `--list-tests` lists all registered tests matching specified test spec.
Usually this listing also includes tags, and potentially also other Usually this listing also includes tags, and potentially also other
information, like source location, based on verbosity and reporter's design. 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-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> <a id="sending-output-to-a-file"></a>
## Sending output to a file ## 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) * Added a support for Bazel integration with `XML_OUTPUT_FILE` env var (#2399)
* This has to be enabled during compilation. * This has to be enabled during compilation.
* Added `--skip-benchmarks` flag to run tests without any `BENCHMARK`s (#2392, #2408) * 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 ### Fixes

View File

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

View File

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

View File

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

View File

@ -9,6 +9,7 @@
#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED #define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
#include <catch2/internal/catch_unique_ptr.hpp> #include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <string> #include <string>
@ -34,6 +35,9 @@ namespace Catch {
public: public:
virtual ~EventListenerFactory(); // = default virtual ~EventListenerFactory(); // = default
virtual IEventListenerPtr create( IConfig const* config ) const = 0; 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; virtual std::string getDescription() const = 0;
}; };
} // namespace Catch } // namespace Catch

View File

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

View File

@ -63,6 +63,19 @@ namespace Catch {
reporter.listReporters(descriptions); 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 } // end anonymous namespace
void TagInfo::add( StringRef spelling ) { void TagInfo::add( StringRef spelling ) {
@ -100,6 +113,10 @@ namespace Catch {
listed = true; listed = true;
listReporters(reporter); listReporters(reporter);
} }
if ( config.listListeners() ) {
listed = true;
listListeners( reporter );
}
return listed; return listed;
} }

View File

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

View File

@ -152,6 +152,33 @@ namespace Catch {
out << '\n' << std::flush; 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, void defaultListTags( std::ostream& out,
std::vector<TagInfo> const& tags, std::vector<TagInfo> const& tags,
bool isFiltered ) { bool isFiltered ) {
@ -233,6 +260,8 @@ namespace Catch {
void EventListenerBase::assertionEnded( AssertionStats const& ) {} void EventListenerBase::assertionEnded( AssertionStats const& ) {}
void EventListenerBase::listReporters( void EventListenerBase::listReporters(
std::vector<ReporterDescription> const& ) {} std::vector<ReporterDescription> const& ) {}
void EventListenerBase::listListeners(
std::vector<ListenerDescription> const& ) {}
void EventListenerBase::listTests( std::vector<TestCaseHandle> const& ) {} void EventListenerBase::listTests( std::vector<TestCaseHandle> const& ) {}
void EventListenerBase::listTags( std::vector<TagInfo> const& ) {} void EventListenerBase::listTags( std::vector<TagInfo> const& ) {}
void EventListenerBase::noMatchingTestCases( StringRef ) {} void EventListenerBase::noMatchingTestCases( StringRef ) {}

View File

@ -29,6 +29,11 @@ namespace Catch {
defaultListReporters(m_stream, descriptions, m_config->verbosity()); 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) { void ReporterBase::listTests(std::vector<TestCaseHandle> const& tests) {
defaultListTests(m_stream, defaultListTests(m_stream,
m_colour.get(), m_colour.get(),

View File

@ -50,6 +50,14 @@ namespace Catch {
*/ */
void listReporters( void listReporters(
std::vector<ReporterDescription> const& descriptions ) override; 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. * Provides a simple default listing of tests.
* *

View File

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

View File

@ -49,6 +49,13 @@ namespace Catch {
std::vector<ReporterDescription> const& descriptions, std::vector<ReporterDescription> const& descriptions,
Verbosity verbosity ); 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 * 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) { void MultiReporter::listTests(std::vector<TestCaseHandle> const& tests) {
for (auto& reporterish : m_reporterLikes) { for (auto& reporterish : m_reporterLikes) {
reporterish->listTests(tests); reporterish->listTests(tests);

View File

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

View File

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

View File

@ -207,6 +207,18 @@ set_tests_properties(List::Reporters::XmlOutput PROPERTIES
FAIL_REGULAR_EXPRESSION "Available reporters:" 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") 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 1 test case
" ( contains: "fake test name" and contains: "fakeTestTag" ) " ( 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!' 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!' 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 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 1 test case
" ( contains: "fake test name" and contains: "fakeTestTag" ) " ( 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!' 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!' 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 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 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" ) " ( 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 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 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" ) " ( 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 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 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"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact <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> <properties>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/> <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 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 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 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="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"> <testcase classname="<exe-name>.global" name="Thrown string literals are translated" time="{duration}" status="run">
<error type="TEST_CASE"> <error type="TEST_CASE">

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="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> <properties>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/> <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 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 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 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="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"> <testcase classname="<exe-name>.global" name="Thrown string literals are translated" time="{duration}" status="run">
<error type="TEST_CASE"> <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 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 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 tests" duration="{duration}"/>
<testCase name="The default listing implementation write to provided stream/Listing listeners" duration="{duration}"/>
</file> </file>
<file path="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp"> <file path="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp">
<testCase name="Cout stream properly declares it writes to stdout" duration="{duration}"/> <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 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 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 tests" duration="{duration}"/>
<testCase name="The default listing implementation write to provided stream/Listing listeners" duration="{duration}"/>
</file> </file>
<file path="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp"> <file path="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp">
<testCase name="Cout stream properly declares it writes to stdout" duration="{duration}"/> <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" ) 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 # 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" ) 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 # This test 'should' fail but doesn't
ok {test-number} - with 1 message: 'oops!' ok {test-number} - with 1 message: 'oops!'
# Thrown string literals are translated # Thrown string literals are translated
@ -4485,5 +4487,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..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" ) 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 # 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" ) 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 # This test 'should' fail but doesn't
ok {test-number} - with 1 message: 'oops!' ok {test-number} - with 1 message: 'oops!'
# Thrown string literals are translated # Thrown string literals are translated
@ -4477,5 +4479,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..2241 1..2242

View File

@ -15754,6 +15754,20 @@ Message from section two
</Expression> </Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/> <OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section> </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"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="This test 'should' fail but doesn't" tags="[!shouldfail][.][failing]" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" > <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> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="2071" failures="143" expectedFailures="27"/> <OverallResults successes="2072" failures="143" expectedFailures="27"/>
<OverallResultsCases successes="301" failures="83" expectedFailures="7"/> <OverallResultsCases successes="301" failures="83" expectedFailures="7"/>
</Catch2TestRun> </Catch2TestRun>

View File

@ -15754,6 +15754,20 @@ Message from section two
</Expression> </Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/> <OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section> </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"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="This test 'should' fail but doesn't" tags="[!shouldfail][.][failing]" filename="tests/<exe-name>/UsageTests/Misc.tests.cpp" > <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> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="2071" failures="143" expectedFailures="27"/> <OverallResults successes="2072" failures="143" expectedFailures="27"/>
<OverallResultsCases successes="301" failures="83" expectedFailures="7"/> <OverallResultsCases successes="301" failures="83" expectedFailures="7"/>
</Catch2TestRun> </Catch2TestRun>

View File

@ -84,6 +84,16 @@ TEST_CASE( "The default listing implementation write to provided stream",
ContainsSubstring( "fake test name"s ) && ContainsSubstring( "fake test name"s ) &&
ContainsSubstring( "fakeTestTag"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]" ) { TEST_CASE( "Reporter's write listings to provided stream", "[reporters]" ) {

View File

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