mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 21:36:11 +01:00
Merge branch 'dev-better-verbosity' of https://github.com/BMBurstein/Catch
This commit is contained in:
commit
cf2678dce6
87
include/external/tbc_text_format.h
vendored
87
include/external/tbc_text_format.h
vendored
@ -53,13 +53,55 @@ namespace Tbc {
|
|||||||
public:
|
public:
|
||||||
Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
|
Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
|
||||||
: attr( _attr )
|
: attr( _attr )
|
||||||
|
{
|
||||||
|
init( _str );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Text( T const& _val, TextAttributes const& _attr = TextAttributes() )
|
||||||
|
: attr( _attr )
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << _val;
|
||||||
|
init( oss.str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef std::vector<std::string>::const_iterator const_iterator;
|
||||||
|
|
||||||
|
const_iterator begin() const { return lines.begin(); }
|
||||||
|
const_iterator end() const { return lines.end(); }
|
||||||
|
std::string const& last() const { return lines.back(); }
|
||||||
|
std::size_t size() const { return lines.size(); }
|
||||||
|
std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
|
||||||
|
std::string toString() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << *this;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
|
||||||
|
for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
|
||||||
|
it != itEnd; ++it ) {
|
||||||
|
if( it != _text.begin() )
|
||||||
|
_stream << "\n";
|
||||||
|
_stream << *it;
|
||||||
|
}
|
||||||
|
return _stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextAttributes attr;
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
|
||||||
|
void init( std::string const& _str )
|
||||||
{
|
{
|
||||||
const std::string wrappableBeforeChars = "[({<\t";
|
const std::string wrappableBeforeChars = "[({<\t";
|
||||||
const std::string wrappableAfterChars = "])}>-,./|\\";
|
const std::string wrappableAfterChars = "])}>-,./|\\";
|
||||||
const std::string wrappableInsteadOfChars = " \n\r";
|
const std::string wrappableInsteadOfChars = " \n\r";
|
||||||
std::string indent = _attr.initialIndent != std::string::npos
|
std::string indent = attr.initialIndent != std::string::npos
|
||||||
? std::string( _attr.initialIndent, ' ' )
|
? std::string( attr.initialIndent, ' ' )
|
||||||
: std::string( _attr.indent, ' ' );
|
: std::string( attr.indent, ' ' );
|
||||||
|
|
||||||
typedef std::string::const_iterator iterator;
|
typedef std::string::const_iterator iterator;
|
||||||
iterator it = _str.begin();
|
iterator it = _str.begin();
|
||||||
@ -74,7 +116,7 @@ namespace Tbc {
|
|||||||
|
|
||||||
|
|
||||||
std::string suffix;
|
std::string suffix;
|
||||||
std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
|
std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), attr.width-static_cast<size_t>( indent.size() ) );
|
||||||
iterator itEnd = it+width;
|
iterator itEnd = it+width;
|
||||||
iterator itNext = _str.end();
|
iterator itNext = _str.end();
|
||||||
|
|
||||||
@ -121,42 +163,11 @@ namespace Tbc {
|
|||||||
}
|
}
|
||||||
lines.push_back( indent + std::string( it, itEnd ) + suffix );
|
lines.push_back( indent + std::string( it, itEnd ) + suffix );
|
||||||
|
|
||||||
if( indent.size() != _attr.indent )
|
if( indent.size() != attr.indent )
|
||||||
indent = std::string( _attr.indent, ' ' );
|
indent = std::string( attr.indent, ' ' );
|
||||||
it = itNext;
|
it = itNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::vector<std::string>::const_iterator const_iterator;
|
|
||||||
|
|
||||||
const_iterator begin() const { return lines.begin(); }
|
|
||||||
const_iterator end() const { return lines.end(); }
|
|
||||||
std::string const& last() const { return lines.back(); }
|
|
||||||
std::size_t size() const { return lines.size(); }
|
|
||||||
std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
|
|
||||||
std::string toString() const {
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << *this;
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
|
|
||||||
for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
|
|
||||||
it != itEnd; ++it ) {
|
|
||||||
if( it != _text.begin() )
|
|
||||||
_stream << "\n";
|
|
||||||
_stream << *it;
|
|
||||||
}
|
|
||||||
return _stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string str;
|
|
||||||
TextAttributes attr;
|
|
||||||
std::vector<std::string> lines;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Tbc
|
} // end namespace Tbc
|
||||||
@ -165,4 +176,4 @@ namespace Tbc {
|
|||||||
} // end outer namespace
|
} // end outer namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
|
#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
|
@ -30,8 +30,6 @@ namespace Catch {
|
|||||||
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; }
|
||||||
|
|
||||||
Verbosity Config::verbosity() const { return m_data.verbosity; }
|
|
||||||
|
|
||||||
std::string Config::getProcessName() const { return m_data.processName; }
|
std::string Config::getProcessName() const { return m_data.processName; }
|
||||||
|
|
||||||
std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
|
std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
|
||||||
@ -54,6 +52,7 @@ namespace Catch {
|
|||||||
bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
|
bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
|
||||||
int Config::abortAfter() const { return m_data.abortAfter; }
|
int Config::abortAfter() const { return m_data.abortAfter; }
|
||||||
bool Config::showInvisibles() const { return m_data.showInvisibles; }
|
bool Config::showInvisibles() const { return m_data.showInvisibles; }
|
||||||
|
Verbosity Config::verbosity() const { return m_data.verbosity; }
|
||||||
|
|
||||||
IStream const* Config::openStream() {
|
IStream const* Config::openStream() {
|
||||||
if( m_data.outputFilename.empty() )
|
if( m_data.outputFilename.empty() )
|
||||||
|
@ -70,8 +70,6 @@ namespace Catch {
|
|||||||
bool listTags() const;
|
bool listTags() const;
|
||||||
bool listReporters() const;
|
bool listReporters() const;
|
||||||
|
|
||||||
Verbosity verbosity() const;
|
|
||||||
|
|
||||||
std::string getProcessName() const;
|
std::string getProcessName() const;
|
||||||
|
|
||||||
std::vector<std::string> const& getReporterNames() const;
|
std::vector<std::string> const& getReporterNames() const;
|
||||||
@ -94,6 +92,7 @@ namespace Catch {
|
|||||||
virtual bool shouldDebugBreak() const override;
|
virtual bool shouldDebugBreak() const override;
|
||||||
virtual int abortAfter() const override;
|
virtual int abortAfter() const override;
|
||||||
virtual bool showInvisibles() const override;
|
virtual bool showInvisibles() const override;
|
||||||
|
virtual Verbosity verbosity() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ namespace Catch {
|
|||||||
IMutableRegistryHub::~IMutableRegistryHub() {}
|
IMutableRegistryHub::~IMutableRegistryHub() {}
|
||||||
IExceptionTranslator::~IExceptionTranslator() {}
|
IExceptionTranslator::~IExceptionTranslator() {}
|
||||||
IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
|
IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
|
||||||
|
|
||||||
IRunner::~IRunner() {}
|
IRunner::~IRunner() {}
|
||||||
IMutableContext::~IMutableContext() {}
|
IMutableContext::~IMutableContext() {}
|
||||||
IConfig::~IConfig() {}
|
IConfig::~IConfig() {}
|
||||||
|
@ -64,6 +64,7 @@ namespace Catch {
|
|||||||
virtual unsigned int rngSeed() const = 0;
|
virtual unsigned int rngSeed() const = 0;
|
||||||
virtual UseColour::YesOrNo useColour() const = 0;
|
virtual UseColour::YesOrNo useColour() const = 0;
|
||||||
virtual std::vector<std::string> const& getSectionsToRun() const = 0;
|
virtual std::vector<std::string> const& getSectionsToRun() const = 0;
|
||||||
|
virtual Verbosity verbosity() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using IConfigPtr = std::shared_ptr<IConfig const>;
|
using IConfigPtr = std::shared_ptr<IConfig const>;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
@ -162,8 +163,9 @@ namespace Catch {
|
|||||||
struct IStreamingReporter {
|
struct IStreamingReporter {
|
||||||
virtual ~IStreamingReporter() = default;
|
virtual ~IStreamingReporter() = default;
|
||||||
|
|
||||||
// Implementing class must also provide the following static method:
|
// Implementing class must also provide the following static methods:
|
||||||
// static std::string getDescription();
|
// static std::string getDescription();
|
||||||
|
// static std::set<Verbosity> getSupportedVerbosities()
|
||||||
|
|
||||||
virtual ReporterPreferences getPreferences() const = 0;
|
virtual ReporterPreferences getPreferences() const = 0;
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include "catch_interfaces_reporter.h"
|
#include "catch_interfaces_reporter.h"
|
||||||
#include "catch_interfaces_testcase.h"
|
#include "catch_interfaces_testcase.h"
|
||||||
|
|
||||||
|
#include "catch_text.h"
|
||||||
|
|
||||||
#include "catch_clara.h" // For TextFlow
|
#include "catch_clara.h" // For TextFlow
|
||||||
|
|
||||||
#include "catch_console_colour.hpp"
|
#include "catch_console_colour.hpp"
|
||||||
@ -43,12 +45,13 @@ namespace Catch {
|
|||||||
|
|
||||||
Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n";
|
Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n";
|
||||||
if( config.verbosity() >= Verbosity::High ) {
|
if( config.verbosity() >= Verbosity::High ) {
|
||||||
std::string description = testCaseInfo.description.empty()
|
TextAttributes descAttr;
|
||||||
? std::string( "(NO DESCRIPTION)" )
|
descAttr.setIndent( 4 );
|
||||||
: testCaseInfo.description;
|
Catch::cout() << Text( testCaseInfo.lineInfo, descAttr ) << std::endl;
|
||||||
Catch::cout()
|
std::string description = testCaseInfo.description;
|
||||||
<< " " << testCaseInfo.lineInfo << "\n"
|
if( description == "" )
|
||||||
<< Column( description ).indent( 4 ) << "\n";
|
description = "(NO DESCRIPTION)";
|
||||||
|
Catch::cout() << Text( description, descAttr ) << std::endl;
|
||||||
}
|
}
|
||||||
if( !testCaseInfo.tags.empty() )
|
if( !testCaseInfo.tags.empty() )
|
||||||
Catch::cout() << Column( testCaseInfo.tagsAsString ).indent( 6 ) << "\n";
|
Catch::cout() << Column( testCaseInfo.tagsAsString ).indent( 6 ) << "\n";
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct AutomakeReporter : StreamingReporterBase {
|
struct AutomakeReporter : StreamingReporterBase<AutomakeReporter> {
|
||||||
AutomakeReporter( ReporterConfig const& _config )
|
AutomakeReporter( ReporterConfig const& _config )
|
||||||
: StreamingReporterBase( _config )
|
: StreamingReporterBase( _config )
|
||||||
{}
|
{}
|
||||||
|
@ -39,181 +39,6 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StreamingReporterBase::StreamingReporterBase(ReporterConfig const& _config)
|
|
||||||
: m_config(_config.fullConfig()),
|
|
||||||
stream(_config.stream())
|
|
||||||
{
|
|
||||||
m_reporterPrefs.shouldRedirectStdOut = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReporterPreferences StreamingReporterBase::getPreferences() const {
|
|
||||||
return m_reporterPrefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamingReporterBase::~StreamingReporterBase() {}
|
|
||||||
|
|
||||||
void StreamingReporterBase::noMatchingTestCases(std::string const &) {}
|
|
||||||
|
|
||||||
void StreamingReporterBase::testRunStarting(TestRunInfo const & _testRunInfo) {
|
|
||||||
currentTestRunInfo = _testRunInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingReporterBase::testGroupStarting(GroupInfo const & _groupInfo) {
|
|
||||||
currentGroupInfo = _groupInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingReporterBase::testCaseStarting(TestCaseInfo const & _testInfo) {
|
|
||||||
currentTestCaseInfo = _testInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingReporterBase::sectionStarting(SectionInfo const & _sectionInfo) {
|
|
||||||
m_sectionStack.push_back(_sectionInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingReporterBase::sectionEnded(SectionStats const &) {
|
|
||||||
m_sectionStack.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingReporterBase::testCaseEnded(TestCaseStats const &) {
|
|
||||||
currentTestCaseInfo.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingReporterBase::testGroupEnded(TestGroupStats const &) {
|
|
||||||
currentGroupInfo.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingReporterBase::testRunEnded(TestRunStats const &) {
|
|
||||||
currentTestCaseInfo.reset();
|
|
||||||
currentGroupInfo.reset();
|
|
||||||
currentTestRunInfo.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamingReporterBase::skipTest(TestCaseInfo const &) {
|
|
||||||
// Don't do anything with this by default.
|
|
||||||
// It can optionally be overridden in the derived class.
|
|
||||||
}
|
|
||||||
|
|
||||||
CumulativeReporterBase::CumulativeReporterBase(ReporterConfig const & _config)
|
|
||||||
: m_config(_config.fullConfig()),
|
|
||||||
stream(_config.stream()) {
|
|
||||||
m_reporterPrefs.shouldRedirectStdOut = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CumulativeReporterBase::~CumulativeReporterBase() {}
|
|
||||||
|
|
||||||
ReporterPreferences CumulativeReporterBase::getPreferences() const {
|
|
||||||
return m_reporterPrefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::testRunStarting(TestRunInfo const &) {}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::testGroupStarting(GroupInfo const &) {}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::testCaseStarting(TestCaseInfo const &) {}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::sectionStarting(SectionInfo const & sectionInfo) {
|
|
||||||
SectionStats incompleteStats(sectionInfo, Counts(), 0, false);
|
|
||||||
std::shared_ptr<SectionNode> node;
|
|
||||||
if (m_sectionStack.empty()) {
|
|
||||||
if (!m_rootSection)
|
|
||||||
m_rootSection = std::make_shared<SectionNode>(incompleteStats);
|
|
||||||
node = m_rootSection;
|
|
||||||
} else {
|
|
||||||
SectionNode& parentNode = *m_sectionStack.back();
|
|
||||||
auto it =
|
|
||||||
std::find_if(parentNode.childSections.begin(),
|
|
||||||
parentNode.childSections.end(),
|
|
||||||
BySectionInfo(sectionInfo));
|
|
||||||
if (it == parentNode.childSections.end()) {
|
|
||||||
node = std::make_shared<SectionNode>(incompleteStats);
|
|
||||||
parentNode.childSections.push_back(node);
|
|
||||||
} else
|
|
||||||
node = *it;
|
|
||||||
}
|
|
||||||
m_sectionStack.push_back(node);
|
|
||||||
m_deepestSection = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::assertionStarting(AssertionInfo const &) {}
|
|
||||||
|
|
||||||
bool CumulativeReporterBase::assertionEnded(AssertionStats const & assertionStats) {
|
|
||||||
assert(!m_sectionStack.empty());
|
|
||||||
SectionNode& sectionNode = *m_sectionStack.back();
|
|
||||||
sectionNode.assertions.push_back(assertionStats);
|
|
||||||
// AssertionResult holds a pointer to a temporary DecomposedExpression,
|
|
||||||
// which getExpandedExpression() calls to build the expression string.
|
|
||||||
// Our section stack copy of the assertionResult will likely outlive the
|
|
||||||
// temporary, so it must be expanded or discarded now to avoid calling
|
|
||||||
// a destroyed object later.
|
|
||||||
prepareExpandedExpression(sectionNode.assertions.back().assertionResult);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::sectionEnded(SectionStats const & sectionStats) {
|
|
||||||
assert(!m_sectionStack.empty());
|
|
||||||
SectionNode& node = *m_sectionStack.back();
|
|
||||||
node.stats = sectionStats;
|
|
||||||
m_sectionStack.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::testCaseEnded(TestCaseStats const & testCaseStats) {
|
|
||||||
auto node = std::make_shared<TestCaseNode>(testCaseStats);
|
|
||||||
assert(m_sectionStack.size() == 0);
|
|
||||||
node->children.push_back(m_rootSection);
|
|
||||||
m_testCases.push_back(node);
|
|
||||||
m_rootSection.reset();
|
|
||||||
|
|
||||||
assert(m_deepestSection);
|
|
||||||
m_deepestSection->stdOut = testCaseStats.stdOut;
|
|
||||||
m_deepestSection->stdErr = testCaseStats.stdErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::testGroupEnded(TestGroupStats const & testGroupStats) {
|
|
||||||
auto node = std::make_shared<TestGroupNode>(testGroupStats);
|
|
||||||
node->children.swap(m_testCases);
|
|
||||||
m_testGroups.push_back(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::testRunEnded(TestRunStats const & testRunStats) {
|
|
||||||
auto node = std::make_shared<TestRunNode>(testRunStats);
|
|
||||||
node->children.swap(m_testGroups);
|
|
||||||
m_testRuns.push_back(node);
|
|
||||||
testRunEndedCumulative();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::skipTest(TestCaseInfo const &) {}
|
|
||||||
|
|
||||||
void CumulativeReporterBase::prepareExpandedExpression(AssertionResult & result) const {
|
|
||||||
if (result.isOk())
|
|
||||||
result.discardDecomposedExpression();
|
|
||||||
else
|
|
||||||
result.expandDecomposedExpression();
|
|
||||||
}
|
|
||||||
|
|
||||||
CumulativeReporterBase::SectionNode::SectionNode(SectionStats const& _stats)
|
|
||||||
:stats(_stats) {}
|
|
||||||
CumulativeReporterBase::SectionNode::~SectionNode() {}
|
|
||||||
|
|
||||||
bool CumulativeReporterBase::SectionNode::operator==(SectionNode const & other) const {
|
|
||||||
return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CumulativeReporterBase::SectionNode::operator==(std::shared_ptr<SectionNode> const& other) const {
|
|
||||||
return operator==(*other);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CumulativeReporterBase::BySectionInfo::BySectionInfo(SectionInfo const& other)
|
|
||||||
:m_other(other) {}
|
|
||||||
|
|
||||||
CumulativeReporterBase::BySectionInfo::BySectionInfo(BySectionInfo const & other)
|
|
||||||
:m_other(other.m_other) {}
|
|
||||||
|
|
||||||
bool CumulativeReporterBase::BySectionInfo::operator()(std::shared_ptr<SectionNode> const & node) const {
|
|
||||||
return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
|
TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
|
||||||
:StreamingReporterBase(_config) {}
|
:StreamingReporterBase(_config) {}
|
||||||
|
|
||||||
|
@ -21,28 +21,62 @@ namespace Catch {
|
|||||||
// Returns double formatted as %.3f (format expected on output)
|
// Returns double formatted as %.3f (format expected on output)
|
||||||
std::string getFormattedDuration( double duration );
|
std::string getFormattedDuration( double duration );
|
||||||
|
|
||||||
|
template<typename DerivedT>
|
||||||
struct StreamingReporterBase : IStreamingReporter {
|
struct StreamingReporterBase : IStreamingReporter {
|
||||||
|
|
||||||
StreamingReporterBase(ReporterConfig const& _config);
|
StreamingReporterBase( ReporterConfig const& _config )
|
||||||
|
: m_config( _config.fullConfig() ),
|
||||||
|
stream( _config.stream() )
|
||||||
|
{
|
||||||
|
m_reporterPrefs.shouldRedirectStdOut = false;
|
||||||
|
CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" );
|
||||||
|
}
|
||||||
|
|
||||||
virtual ReporterPreferences getPreferences() const override;
|
virtual ReporterPreferences getPreferences() const override {
|
||||||
|
return m_reporterPrefs;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~StreamingReporterBase() override;
|
static std::set<Verbosity> getSupportedVerbosities() {
|
||||||
|
return { Verbosity::Normal };
|
||||||
|
}
|
||||||
|
|
||||||
virtual void noMatchingTestCases(std::string const&) override;
|
virtual ~StreamingReporterBase() override = default;
|
||||||
|
|
||||||
virtual void testRunStarting(TestRunInfo const& _testRunInfo) override;
|
virtual void noMatchingTestCases(std::string const&) override {}
|
||||||
virtual void testGroupStarting(GroupInfo const& _groupInfo) override;
|
|
||||||
|
|
||||||
virtual void testCaseStarting(TestCaseInfo const& _testInfo) override;
|
virtual void testRunStarting(TestRunInfo const& _testRunInfo) override {
|
||||||
virtual void sectionStarting(SectionInfo const& _sectionInfo) override;
|
currentTestRunInfo = _testRunInfo;
|
||||||
|
}
|
||||||
|
virtual void testGroupStarting(GroupInfo const& _groupInfo) override {
|
||||||
|
currentGroupInfo = _groupInfo;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void sectionEnded(SectionStats const& /* _sectionStats */) override;
|
virtual void testCaseStarting(TestCaseInfo const& _testInfo) override {
|
||||||
virtual void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override;
|
currentTestCaseInfo = _testInfo;
|
||||||
virtual void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override;
|
}
|
||||||
virtual void testRunEnded(TestRunStats const& /* _testRunStats */) override;
|
virtual void sectionStarting(SectionInfo const& _sectionInfo) override {
|
||||||
|
m_sectionStack.push_back(_sectionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void skipTest(TestCaseInfo const&) override;
|
virtual void sectionEnded(SectionStats const& /* _sectionStats */) override {
|
||||||
|
m_sectionStack.pop_back();
|
||||||
|
}
|
||||||
|
virtual void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
|
||||||
|
currentTestCaseInfo.reset();
|
||||||
|
}
|
||||||
|
virtual void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override {
|
||||||
|
currentGroupInfo.reset();
|
||||||
|
}
|
||||||
|
virtual void testRunEnded(TestRunStats const& /* _testRunStats */) override {
|
||||||
|
currentTestCaseInfo.reset();
|
||||||
|
currentGroupInfo.reset();
|
||||||
|
currentTestRunInfo.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void skipTest(TestCaseInfo const&) override {
|
||||||
|
// Don't do anything with this by default.
|
||||||
|
// It can optionally be overridden in the derived class.
|
||||||
|
}
|
||||||
|
|
||||||
IConfigPtr m_config;
|
IConfigPtr m_config;
|
||||||
std::ostream& stream;
|
std::ostream& stream;
|
||||||
@ -55,6 +89,7 @@ namespace Catch {
|
|||||||
ReporterPreferences m_reporterPrefs;
|
ReporterPreferences m_reporterPrefs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename DerivedT>
|
||||||
struct CumulativeReporterBase : IStreamingReporter {
|
struct CumulativeReporterBase : IStreamingReporter {
|
||||||
template<typename T, typename ChildNodeT>
|
template<typename T, typename ChildNodeT>
|
||||||
struct Node {
|
struct Node {
|
||||||
@ -66,11 +101,15 @@ namespace Catch {
|
|||||||
ChildNodes children;
|
ChildNodes children;
|
||||||
};
|
};
|
||||||
struct SectionNode {
|
struct SectionNode {
|
||||||
explicit SectionNode(SectionStats const& _stats);
|
explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
|
||||||
virtual ~SectionNode();
|
virtual ~SectionNode() = default;
|
||||||
|
|
||||||
bool operator == (SectionNode const& other) const;
|
bool operator == (SectionNode const& other) const {
|
||||||
bool operator == (std::shared_ptr<SectionNode> const& other) const;
|
return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
|
||||||
|
}
|
||||||
|
bool operator == (std::shared_ptr<SectionNode> const& other) const {
|
||||||
|
return operator==(*other);
|
||||||
|
}
|
||||||
|
|
||||||
SectionStats stats;
|
SectionStats stats;
|
||||||
using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
|
using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
|
||||||
@ -82,9 +121,11 @@ namespace Catch {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct BySectionInfo {
|
struct BySectionInfo {
|
||||||
BySectionInfo(SectionInfo const& other);
|
BySectionInfo(SectionInfo const& other) : m_other(other) {}
|
||||||
BySectionInfo(BySectionInfo const& other);
|
BySectionInfo(BySectionInfo const& other) : m_other(other.m_other) {}
|
||||||
bool operator() (std::shared_ptr<SectionNode> const& node) const;
|
bool operator() (std::shared_ptr<SectionNode> const& node) const {
|
||||||
|
return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
|
||||||
|
}
|
||||||
void operator=(BySectionInfo const&) = delete;
|
void operator=(BySectionInfo const&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -96,30 +137,105 @@ namespace Catch {
|
|||||||
using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
|
using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
|
||||||
using TestRunNode = Node<TestRunStats, TestGroupNode>;
|
using TestRunNode = Node<TestRunStats, TestGroupNode>;
|
||||||
|
|
||||||
CumulativeReporterBase(ReporterConfig const& _config);
|
CumulativeReporterBase( ReporterConfig const& _config )
|
||||||
~CumulativeReporterBase();
|
: m_config( _config.fullConfig() ),
|
||||||
|
stream( _config.stream() )
|
||||||
|
{
|
||||||
|
m_reporterPrefs.shouldRedirectStdOut = false;
|
||||||
|
CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" );
|
||||||
|
}
|
||||||
|
virtual ~CumulativeReporterBase() = default;
|
||||||
|
|
||||||
virtual ReporterPreferences getPreferences() const override;
|
virtual ReporterPreferences getPreferences() const override {
|
||||||
|
return m_reporterPrefs;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void testRunStarting(TestRunInfo const&) override;
|
static std::set<Verbosity> getSupportedVerbosities() {
|
||||||
virtual void testGroupStarting(GroupInfo const&) override;
|
return { Verbosity::Normal };
|
||||||
|
}
|
||||||
|
|
||||||
virtual void testCaseStarting(TestCaseInfo const&) override;
|
virtual void testRunStarting( TestRunInfo const& ) override {}
|
||||||
|
virtual void testGroupStarting( GroupInfo const& ) override {}
|
||||||
|
|
||||||
virtual void sectionStarting(SectionInfo const& sectionInfo) override;
|
virtual void testCaseStarting( TestCaseInfo const& ) override {}
|
||||||
|
|
||||||
virtual void assertionStarting(AssertionInfo const&) override;
|
virtual void sectionStarting( SectionInfo const& sectionInfo ) override {
|
||||||
|
SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
|
||||||
|
std::shared_ptr<SectionNode> node;
|
||||||
|
if( m_sectionStack.empty() ) {
|
||||||
|
if( !m_rootSection )
|
||||||
|
m_rootSection = std::make_shared<SectionNode>( incompleteStats );
|
||||||
|
node = m_rootSection;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SectionNode& parentNode = *m_sectionStack.back();
|
||||||
|
typename SectionNode::ChildSections::const_iterator it =
|
||||||
|
std::find_if( parentNode.childSections.begin(),
|
||||||
|
parentNode.childSections.end(),
|
||||||
|
BySectionInfo( sectionInfo ) );
|
||||||
|
if( it == parentNode.childSections.end() ) {
|
||||||
|
node = std::make_shared<SectionNode>( incompleteStats );
|
||||||
|
parentNode.childSections.push_back( node );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
node = *it;
|
||||||
|
}
|
||||||
|
m_sectionStack.push_back( node );
|
||||||
|
m_deepestSection = node;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool assertionEnded(AssertionStats const& assertionStats) override;
|
virtual void assertionStarting(AssertionInfo const&) override {}
|
||||||
virtual void sectionEnded(SectionStats const& sectionStats) override;
|
|
||||||
virtual void testCaseEnded(TestCaseStats const& testCaseStats) override;
|
virtual bool assertionEnded(AssertionStats const& assertionStats) override {
|
||||||
virtual void testGroupEnded(TestGroupStats const& testGroupStats) override;
|
assert(!m_sectionStack.empty());
|
||||||
virtual void testRunEnded(TestRunStats const& testRunStats) override;
|
SectionNode& sectionNode = *m_sectionStack.back();
|
||||||
|
sectionNode.assertions.push_back(assertionStats);
|
||||||
|
// AssertionResult holds a pointer to a temporary DecomposedExpression,
|
||||||
|
// which getExpandedExpression() calls to build the expression string.
|
||||||
|
// Our section stack copy of the assertionResult will likely outlive the
|
||||||
|
// temporary, so it must be expanded or discarded now to avoid calling
|
||||||
|
// a destroyed object later.
|
||||||
|
prepareExpandedExpression(sectionNode.assertions.back().assertionResult);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual void sectionEnded(SectionStats const& sectionStats) override {
|
||||||
|
assert(!m_sectionStack.empty());
|
||||||
|
SectionNode& node = *m_sectionStack.back();
|
||||||
|
node.stats = sectionStats;
|
||||||
|
m_sectionStack.pop_back();
|
||||||
|
}
|
||||||
|
virtual void testCaseEnded(TestCaseStats const& testCaseStats) override {
|
||||||
|
auto node = std::make_shared<TestCaseNode>(testCaseStats);
|
||||||
|
assert(m_sectionStack.size() == 0);
|
||||||
|
node->children.push_back(m_rootSection);
|
||||||
|
m_testCases.push_back(node);
|
||||||
|
m_rootSection.reset();
|
||||||
|
|
||||||
|
assert(m_deepestSection);
|
||||||
|
m_deepestSection->stdOut = testCaseStats.stdOut;
|
||||||
|
m_deepestSection->stdErr = testCaseStats.stdErr;
|
||||||
|
}
|
||||||
|
virtual void testGroupEnded(TestGroupStats const& testGroupStats) override {
|
||||||
|
auto node = std::make_shared<TestGroupNode>(testGroupStats);
|
||||||
|
node->children.swap(m_testCases);
|
||||||
|
m_testGroups.push_back(node);
|
||||||
|
}
|
||||||
|
virtual void testRunEnded(TestRunStats const& testRunStats) override {
|
||||||
|
auto node = std::make_shared<TestRunNode>(testRunStats);
|
||||||
|
node->children.swap(m_testGroups);
|
||||||
|
m_testRuns.push_back(node);
|
||||||
|
testRunEndedCumulative();
|
||||||
|
}
|
||||||
virtual void testRunEndedCumulative() = 0;
|
virtual void testRunEndedCumulative() = 0;
|
||||||
|
|
||||||
virtual void skipTest(TestCaseInfo const&) override;
|
virtual void skipTest(TestCaseInfo const&) override {}
|
||||||
|
|
||||||
virtual void prepareExpandedExpression(AssertionResult& result) const;
|
virtual void prepareExpandedExpression(AssertionResult& result) const {
|
||||||
|
if (result.isOk())
|
||||||
|
result.discardDecomposedExpression();
|
||||||
|
else
|
||||||
|
result.expandDecomposedExpression();
|
||||||
|
}
|
||||||
|
|
||||||
IConfigPtr m_config;
|
IConfigPtr m_config;
|
||||||
std::ostream& stream;
|
std::ostream& stream;
|
||||||
@ -147,8 +263,8 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct TestEventListenerBase : StreamingReporterBase {
|
struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
|
||||||
TestEventListenerBase(ReporterConfig const& _config);
|
TestEventListenerBase( ReporterConfig const& _config );
|
||||||
|
|
||||||
virtual void assertionStarting(AssertionInfo const&) override;
|
virtual void assertionStarting(AssertionInfo const&) override;
|
||||||
virtual bool assertionEnded(AssertionStats const&) override;
|
virtual bool assertionEnded(AssertionStats const&) override;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct CompactReporter : StreamingReporterBase {
|
struct CompactReporter : StreamingReporterBase<CompactReporter> {
|
||||||
|
|
||||||
using StreamingReporterBase::StreamingReporterBase;
|
using StreamingReporterBase::StreamingReporterBase;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct ConsoleReporter : StreamingReporterBase {
|
struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
|
||||||
using StreamingReporterBase::StreamingReporterBase;
|
using StreamingReporterBase::StreamingReporterBase;
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ namespace Catch {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class JunitReporter : public CumulativeReporterBase {
|
class JunitReporter : public CumulativeReporterBase<JunitReporter> {
|
||||||
public:
|
public:
|
||||||
JunitReporter( ReporterConfig const& _config )
|
JunitReporter( ReporterConfig const& _config )
|
||||||
: CumulativeReporterBase( _config ),
|
: CumulativeReporterBase( _config ),
|
||||||
|
@ -18,6 +18,11 @@ namespace Catch {
|
|||||||
return m_reporters[0]->getPreferences();
|
return m_reporters[0]->getPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<Verbosity> getSupportedVerbosities() {
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MultipleReporters::noMatchingTestCases( std::string const& spec ) {
|
void MultipleReporters::noMatchingTestCases( std::string const& spec ) {
|
||||||
for( auto const& reporter : m_reporters )
|
for( auto const& reporter : m_reporters )
|
||||||
reporter->noMatchingTestCases( spec );
|
reporter->noMatchingTestCases( spec );
|
||||||
|
64
include/reporters/catch_reporter_multi.hpp
Normal file
64
include/reporters/catch_reporter_multi.hpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
*/
|
||||||
|
#ifndef TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "../internal/catch_interfaces_reporter.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
class MultipleReporters : public IStreamingReporter {
|
||||||
|
typedef std::vector<IStreamingReporterPtr> Reporters;
|
||||||
|
Reporters m_reporters;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void add( IStreamingReporterPtr&& reporter );
|
||||||
|
|
||||||
|
public: // IStreamingReporter
|
||||||
|
|
||||||
|
virtual ReporterPreferences getPreferences() const override;
|
||||||
|
|
||||||
|
static std::set<Verbosity> getSupportedVerbosities();
|
||||||
|
|
||||||
|
virtual void noMatchingTestCases( std::string const& spec ) override;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void testRunStarting( TestRunInfo const& testRunInfo ) override;
|
||||||
|
|
||||||
|
virtual void testGroupStarting( GroupInfo const& groupInfo ) override;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void testCaseStarting( TestCaseInfo const& testInfo ) override;
|
||||||
|
|
||||||
|
virtual void sectionStarting( SectionInfo const& sectionInfo ) override;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void assertionStarting( AssertionInfo const& assertionInfo ) override;
|
||||||
|
|
||||||
|
|
||||||
|
// The return value indicates if the messages buffer should be cleared:
|
||||||
|
virtual bool assertionEnded( AssertionStats const& assertionStats ) override;
|
||||||
|
|
||||||
|
virtual void sectionEnded( SectionStats const& sectionStats ) override;
|
||||||
|
|
||||||
|
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override;
|
||||||
|
|
||||||
|
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override;
|
||||||
|
|
||||||
|
virtual void testRunEnded( TestRunStats const& testRunStats ) override;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void skipTest( TestCaseInfo const& testInfo ) override;
|
||||||
|
|
||||||
|
virtual bool isMulti() const override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace Catch
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct TAPReporter : StreamingReporterBase {
|
struct TAPReporter : StreamingReporterBase<TAPReporter> {
|
||||||
|
|
||||||
using StreamingReporterBase::StreamingReporterBase;
|
using StreamingReporterBase::StreamingReporterBase;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace Catch {
|
|||||||
|
|
||||||
using namespace clara::TextFlow;
|
using namespace clara::TextFlow;
|
||||||
|
|
||||||
struct TeamCityReporter : StreamingReporterBase {
|
struct TeamCityReporter : StreamingReporterBase<TeamCityReporter> {
|
||||||
TeamCityReporter( ReporterConfig const& _config )
|
TeamCityReporter( ReporterConfig const& _config )
|
||||||
: StreamingReporterBase( _config )
|
: StreamingReporterBase( _config )
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include "../internal/catch_timer.h"
|
#include "../internal/catch_timer.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
class XmlReporter : public StreamingReporterBase {
|
class XmlReporter : public StreamingReporterBase<XmlReporter> {
|
||||||
public:
|
public:
|
||||||
XmlReporter( ReporterConfig const& _config )
|
XmlReporter( ReporterConfig const& _config )
|
||||||
: StreamingReporterBase( _config ),
|
: StreamingReporterBase( _config ),
|
||||||
|
Loading…
Reference in New Issue
Block a user