mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-28 15:25:39 +02:00
Add support for multiple parallel reporters
This requires a bunch of different changes across the reporter subsystem. * We need to handle multiple reporters and their differing preferences in `ListeningReporter`, e.g. what to do when we mix reporters that capture and don't capture stdout. * We need to change how the reporter is given output and how we parse reporter's output destination from CLI. * Approval tests need to handle multireporter option
This commit is contained in:

committed by
Martin Hořeňovský

parent
6b55f5d780
commit
ccd67b293d
@@ -14,6 +14,7 @@
|
||||
#include <catch2/interfaces/catch_interfaces_reporter_registry.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
@@ -133,15 +134,56 @@ namespace Catch {
|
||||
return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + '\'' );
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
};
|
||||
auto const setReporter = [&]( std::string const& reporter ) {
|
||||
auto const setReporter = [&]( std::string const& reporterSpec ) {
|
||||
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
|
||||
|
||||
auto result = factories.find( reporter );
|
||||
// clear the default reporter
|
||||
if (!config._nonDefaultReporterSpecifications) {
|
||||
config.reporterSpecifications.clear();
|
||||
config._nonDefaultReporterSpecifications = true;
|
||||
}
|
||||
|
||||
// Exactly one of the reporters may be specified without an output
|
||||
// file, in which case it defaults to the output specified by "-o"
|
||||
// (or standard output).
|
||||
static constexpr auto separator = "::";
|
||||
static constexpr size_t separatorSize = 2;
|
||||
auto separatorPos = reporterSpec.find( separator );
|
||||
const bool containsFileName = separatorPos != reporterSpec.npos;
|
||||
std::string reporterName;
|
||||
Optional<std::string> outputFileName;
|
||||
if (!containsFileName) {
|
||||
reporterName = reporterSpec;
|
||||
} else {
|
||||
reporterName = reporterSpec.substr( 0, separatorPos );
|
||||
outputFileName = reporterSpec.substr(
|
||||
separatorPos + separatorSize, reporterSpec.size() );
|
||||
}
|
||||
|
||||
auto result = factories.find( reporterName );
|
||||
|
||||
if( result == factories.end() )
|
||||
return ParserResult::runtimeError( "Unrecognized reporter, '" + reporterName + "'. Check available with --list-reporters" );
|
||||
if( containsFileName && outputFileName->empty() )
|
||||
return ParserResult::runtimeError( "Reporter '" + reporterName + "' has empty filename specified as its output. Supply a filename or remove the colons to use the default output." );
|
||||
|
||||
config.reporterSpecifications.push_back({ std::move(reporterName), std::move(outputFileName) });
|
||||
|
||||
// It would be enough to check this only once at the very end, but there is
|
||||
// not a place where we could call this check, so do it every time it could fail.
|
||||
// For valid inputs, this is still called at most once.
|
||||
if (!containsFileName) {
|
||||
int n_reporters_without_file = 0;
|
||||
for (auto const& spec : config.reporterSpecifications) {
|
||||
if (spec.outputFileName.none()) {
|
||||
n_reporters_without_file++;
|
||||
}
|
||||
}
|
||||
if (n_reporters_without_file > 1) {
|
||||
return ParserResult::runtimeError( "Only one reporter may have unspecified output file." );
|
||||
}
|
||||
}
|
||||
|
||||
if( factories.end() != result )
|
||||
config.reporterName = reporter;
|
||||
else
|
||||
return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" );
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
};
|
||||
auto const setShardCount = [&]( std::string const& shardCount ) {
|
||||
@@ -202,10 +244,10 @@ namespace Catch {
|
||||
| Opt( config.showInvisibles )
|
||||
["-i"]["--invisibles"]
|
||||
( "show invisibles (tabs, newlines)" )
|
||||
| Opt( config.outputFilename, "filename" )
|
||||
| Opt( config.defaultOutputFilename, "filename" )
|
||||
["-o"]["--out"]
|
||||
( "output filename" )
|
||||
| Opt( setReporter, "name" )
|
||||
( "default output filename" )
|
||||
| Opt( accept_many, setReporter, "name[:output-file]" )
|
||||
["-r"]["--reporter"]
|
||||
( "reporter to use (defaults to console)" )
|
||||
| Opt( config.name, "name" )
|
||||
|
Reference in New Issue
Block a user