mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	Call listeners before calling reporters
Catch2's documentation promises that listeners are called _before_ reporters, but because of the previous implementation, they were called _after_ reporters. This commit fixes that. Closes #1234
This commit is contained in:
		| @@ -265,7 +265,7 @@ set(REPORTER_HEADERS | |||||||
|         ${HEADER_DIR}/reporters/catch_reporter_compact.h |         ${HEADER_DIR}/reporters/catch_reporter_compact.h | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_console.h |         ${HEADER_DIR}/reporters/catch_reporter_console.h | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_junit.h |         ${HEADER_DIR}/reporters/catch_reporter_junit.h | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_multi.h |         ${HEADER_DIR}/reporters/catch_reporter_listening.h | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_tap.hpp |         ${HEADER_DIR}/reporters/catch_reporter_tap.hpp | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp |         ${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_xml.h |         ${HEADER_DIR}/reporters/catch_reporter_xml.h | ||||||
| @@ -275,7 +275,7 @@ set(REPORTER_SOURCES | |||||||
|         ${HEADER_DIR}/reporters/catch_reporter_compact.cpp |         ${HEADER_DIR}/reporters/catch_reporter_compact.cpp | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_console.cpp |         ${HEADER_DIR}/reporters/catch_reporter_console.cpp | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_junit.cpp |         ${HEADER_DIR}/reporters/catch_reporter_junit.cpp | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_multi.cpp |         ${HEADER_DIR}/reporters/catch_reporter_listening.cpp | ||||||
|         ${HEADER_DIR}/reporters/catch_reporter_xml.cpp |         ${HEADER_DIR}/reporters/catch_reporter_xml.cpp | ||||||
|         ) |         ) | ||||||
| set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES}) | set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES}) | ||||||
|   | |||||||
| @@ -54,14 +54,12 @@ namespace Catch { | |||||||
|         std::string outputFilename; |         std::string outputFilename; | ||||||
|         std::string name; |         std::string name; | ||||||
|         std::string processName; |         std::string processName; | ||||||
|  |  | ||||||
| #ifndef CATCH_CONFIG_DEFAULT_REPORTER | #ifndef CATCH_CONFIG_DEFAULT_REPORTER | ||||||
| #define CATCH_CONFIG_DEFAULT_REPORTER "console" | #define CATCH_CONFIG_DEFAULT_REPORTER "console" | ||||||
| #endif | #endif | ||||||
|         std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; |         std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; | ||||||
| #undef CATCH_CONFIG_DEFAULT_REPORTER | #undef CATCH_CONFIG_DEFAULT_REPORTER | ||||||
|  |  | ||||||
|  |  | ||||||
|         std::vector<std::string> testsOrTags; |         std::vector<std::string> testsOrTags; | ||||||
|         std::vector<std::string> sectionsToRun; |         std::vector<std::string> sectionsToRun; | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "catch_interfaces_reporter.h" | #include "catch_interfaces_reporter.h" | ||||||
| #include "../reporters/catch_reporter_multi.h" | #include "../reporters/catch_reporter_listening.h" | ||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
|  |  | ||||||
| @@ -111,25 +111,4 @@ namespace Catch { | |||||||
|     IReporterFactory::~IReporterFactory() = default; |     IReporterFactory::~IReporterFactory() = default; | ||||||
|     IReporterRegistry::~IReporterRegistry() = default; |     IReporterRegistry::~IReporterRegistry() = default; | ||||||
|  |  | ||||||
|     void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { |  | ||||||
|  |  | ||||||
|         if( !existingReporter ) { |  | ||||||
|             existingReporter = std::move( additionalReporter ); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         MultipleReporters* multi = nullptr; |  | ||||||
|  |  | ||||||
|         if( existingReporter->isMulti() ) { |  | ||||||
|             multi = static_cast<MultipleReporters*>( existingReporter.get() ); |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             auto newMulti = std::unique_ptr<MultipleReporters>( new MultipleReporters ); |  | ||||||
|             newMulti->add( std::move( existingReporter ) ); |  | ||||||
|             multi = newMulti.get(); |  | ||||||
|             existingReporter = std::move( newMulti ); |  | ||||||
|         } |  | ||||||
|         multi->add( std::move( additionalReporter ) ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } // end namespace Catch | } // end namespace Catch | ||||||
|   | |||||||
| @@ -226,8 +226,6 @@ namespace Catch { | |||||||
|         virtual Listeners const& getListeners() const = 0; |         virtual Listeners const& getListeners() const = 0; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ); |  | ||||||
|  |  | ||||||
| } // end namespace Catch | } // end namespace Catch | ||||||
|  |  | ||||||
| #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED | #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ | |||||||
| #include "catch_text.h" | #include "catch_text.h" | ||||||
| #include "catch_stream.h" | #include "catch_stream.h" | ||||||
| #include "catch_windows_h_proxy.h" | #include "catch_windows_h_proxy.h" | ||||||
|  | #include "../reporters/catch_reporter_listening.h" | ||||||
|  |  | ||||||
| #include <cstdlib> | #include <cstdlib> | ||||||
| #include <iomanip> | #include <iomanip> | ||||||
| @@ -36,22 +37,26 @@ namespace Catch { | |||||||
|             return reporter; |             return reporter; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) { |         IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) { | ||||||
|             return createReporter(config->getReporterName(), config); |             if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { | ||||||
|         } |                 return createReporter(config->getReporterName(), config); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter); | ||||||
|  |  | ||||||
|         void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) { |  | ||||||
|             auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); |             auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); | ||||||
|             for (auto const& listener : listeners) |             for (auto const& listener : listeners) { | ||||||
|                 addReporter(reporters, listener->create(Catch::ReporterConfig(config))); |                 multi->addListener(listener->create(Catch::ReporterConfig(config))); | ||||||
|  |             } | ||||||
|  |             multi->addReporter(createReporter(config->getReporterName(), config)); | ||||||
|  |             return std::move(multi); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         Catch::Totals runTests(std::shared_ptr<Config> const& config) { |         Catch::Totals runTests(std::shared_ptr<Config> const& config) { | ||||||
|             IStreamingReporterPtr reporter = makeReporter(config); |             // FixMe: Add listeners in order first, then add reporters. | ||||||
|             addListeners(reporter, config); |  | ||||||
|  |             auto reporter = makeReporter(config); | ||||||
|  |  | ||||||
|             RunContext context(config, std::move(reporter)); |             RunContext context(config, std::move(reporter)); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										136
									
								
								include/reporters/catch_reporter_listening.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								include/reporters/catch_reporter_listening.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | |||||||
|  | /* | ||||||
|  |  *  Created by Phil on 5/08/2015. | ||||||
|  |  *  Copyright 2015 Two Blue Cubes Ltd. All rights reserved. | ||||||
|  |  * | ||||||
|  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||||
|  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  #include "catch_reporter_listening.h" | ||||||
|  | #include <cassert> | ||||||
|  |  | ||||||
|  | namespace Catch { | ||||||
|  |  | ||||||
|  |     void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { | ||||||
|  |         m_listeners.push_back( std::move( listener ) ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { | ||||||
|  |         assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); | ||||||
|  |         m_reporter = std::move( reporter ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ReporterPreferences ListeningReporter::getPreferences() const { | ||||||
|  |         return m_reporter->getPreferences(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::set<Verbosity> ListeningReporter::getSupportedVerbosities() { | ||||||
|  |         return std::set<Verbosity>{ }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     void ListeningReporter::noMatchingTestCases( std::string const& spec ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->noMatchingTestCases( spec ); | ||||||
|  |         } | ||||||
|  |         m_reporter->noMatchingTestCases( spec ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->benchmarkStarting( benchmarkInfo ); | ||||||
|  |         } | ||||||
|  |         m_reporter->benchmarkStarting( benchmarkInfo ); | ||||||
|  |     } | ||||||
|  |     void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->benchmarkEnded( benchmarkStats ); | ||||||
|  |         } | ||||||
|  |         m_reporter->benchmarkEnded( benchmarkStats ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->testRunStarting( testRunInfo ); | ||||||
|  |         } | ||||||
|  |         m_reporter->testRunStarting( testRunInfo ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->testGroupStarting( groupInfo ); | ||||||
|  |         } | ||||||
|  |         m_reporter->testGroupStarting( groupInfo ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->testCaseStarting( testInfo ); | ||||||
|  |         } | ||||||
|  |         m_reporter->testCaseStarting( testInfo ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->sectionStarting( sectionInfo ); | ||||||
|  |         } | ||||||
|  |         m_reporter->sectionStarting( sectionInfo ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->assertionStarting( assertionInfo ); | ||||||
|  |         } | ||||||
|  |         m_reporter->assertionStarting( assertionInfo ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // The return value indicates if the messages buffer should be cleared: | ||||||
|  |     bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { | ||||||
|  |         for( auto const& listener : m_listeners ) { | ||||||
|  |             static_cast<void>( listener->assertionEnded( assertionStats ) ); | ||||||
|  |         } | ||||||
|  |         return m_reporter->assertionEnded( assertionStats ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->sectionEnded( sectionStats ); | ||||||
|  |         } | ||||||
|  |         m_reporter->sectionEnded( sectionStats ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->testCaseEnded( testCaseStats ); | ||||||
|  |         } | ||||||
|  |         m_reporter->testCaseEnded( testCaseStats ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->testGroupEnded( testGroupStats ); | ||||||
|  |         } | ||||||
|  |         m_reporter->testGroupEnded( testGroupStats ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->testRunEnded( testRunStats ); | ||||||
|  |         } | ||||||
|  |         m_reporter->testRunEnded( testRunStats ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { | ||||||
|  |         for ( auto const& listener : m_listeners ) { | ||||||
|  |             listener->skipTest( testInfo ); | ||||||
|  |         } | ||||||
|  |         m_reporter->skipTest( testInfo ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool ListeningReporter::isMulti() const { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } // end namespace Catch | ||||||
| @@ -11,12 +11,14 @@ | |||||||
| 
 | 
 | ||||||
| namespace Catch { | namespace Catch { | ||||||
| 
 | 
 | ||||||
|     class MultipleReporters : public IStreamingReporter { |     class ListeningReporter : public IStreamingReporter { | ||||||
|         using Reporters = std::vector<IStreamingReporterPtr>; |         using Reporters = std::vector<IStreamingReporterPtr>; | ||||||
|         Reporters m_reporters; |         Reporters m_listeners; | ||||||
|  |         IStreamingReporterPtr m_reporter = nullptr; | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         void add( IStreamingReporterPtr&& reporter ); |         void addListener( IStreamingReporterPtr&& listener ); | ||||||
|  |         void addReporter( IStreamingReporterPtr&& reporter ); | ||||||
| 
 | 
 | ||||||
|     public: // IStreamingReporter
 |     public: // IStreamingReporter
 | ||||||
| 
 | 
 | ||||||
| @@ -1,104 +0,0 @@ | |||||||
| /* |  | ||||||
|  *  Created by Phil on 5/08/2015. |  | ||||||
|  *  Copyright 2015 Two Blue Cubes Ltd. All rights reserved. |  | ||||||
|  * |  | ||||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying |  | ||||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
|  #include "catch_reporter_multi.h" |  | ||||||
|  |  | ||||||
| namespace Catch { |  | ||||||
|  |  | ||||||
|     void MultipleReporters::add( IStreamingReporterPtr&& reporter ) { |  | ||||||
|         m_reporters.push_back( std::move( reporter ) ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ReporterPreferences MultipleReporters::getPreferences() const { |  | ||||||
|         return m_reporters[0]->getPreferences(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::set<Verbosity> MultipleReporters::getSupportedVerbosities() { |  | ||||||
|         return std::set<Verbosity>{ }; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     void MultipleReporters::noMatchingTestCases( std::string const& spec ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->noMatchingTestCases( spec ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->benchmarkStarting( benchmarkInfo ); |  | ||||||
|     } |  | ||||||
|     void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->benchmarkEnded( benchmarkStats ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->testRunStarting( testRunInfo ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->testGroupStarting( groupInfo ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->testCaseStarting( testInfo ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->sectionStarting( sectionInfo ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->assertionStarting( assertionInfo ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // The return value indicates if the messages buffer should be cleared: |  | ||||||
|     bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) { |  | ||||||
|         bool clearBuffer = false; |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             clearBuffer |= reporter->assertionEnded( assertionStats ); |  | ||||||
|         return clearBuffer; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->sectionEnded( sectionStats ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->testCaseEnded( testCaseStats ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->testGroupEnded( testGroupStats ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->testRunEnded( testRunStats ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) { |  | ||||||
|         for( auto const& reporter : m_reporters ) |  | ||||||
|             reporter->skipTest( testInfo ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool MultipleReporters::isMulti() const { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } // end namespace Catch |  | ||||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský