Merge branch 'dev-better-verbosity' of https://github.com/BMBurstein/Catch

This commit is contained in:
Martin Hořeňovský 2017-07-19 23:15:54 +02:00
commit cf2678dce6
18 changed files with 293 additions and 269 deletions

View File

@ -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

View File

@ -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() )

View File

@ -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:

View File

@ -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() {}

View File

@ -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>;

View File

@ -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;

View File

@ -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";

View File

@ -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 )
{} {}

View File

@ -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) {}

View File

@ -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;

View File

@ -13,7 +13,7 @@
namespace Catch { namespace Catch {
struct CompactReporter : StreamingReporterBase { struct CompactReporter : StreamingReporterBase<CompactReporter> {
using StreamingReporterBase::StreamingReporterBase; using StreamingReporterBase::StreamingReporterBase;

View File

@ -18,7 +18,7 @@
namespace Catch { namespace Catch {
struct ConsoleReporter : StreamingReporterBase { struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
using StreamingReporterBase::StreamingReporterBase; using StreamingReporterBase::StreamingReporterBase;

View File

@ -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 ),

View File

@ -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 );

View 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

View File

@ -19,7 +19,7 @@
namespace Catch { namespace Catch {
struct TAPReporter : StreamingReporterBase { struct TAPReporter : StreamingReporterBase<TAPReporter> {
using StreamingReporterBase::StreamingReporterBase; using StreamingReporterBase::StreamingReporterBase;

View File

@ -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 )
{ {

View File

@ -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 ),