Completed CumulativeReporterBase and reimplemented JUnitReporter in terms of it

This commit is contained in:
Phil Nash
2013-08-15 18:39:55 +01:00
parent 1f519dd856
commit 2ddb9d3802
9 changed files with 601 additions and 270 deletions

View File

@@ -116,7 +116,9 @@ namespace Catch {
bool empty() const {
return file.empty();
}
bool operator == ( SourceLineInfo const& other ) const {
return line == other.line && file == other.file;
}
std::string file;
std::size_t line;
};

View File

@@ -58,6 +58,8 @@ namespace Catch {
TestCaseStats::~TestCaseStats() {}
TestGroupStats::~TestGroupStats() {}
TestRunStats::~TestRunStats() {}
CumulativeReporterBase::SectionNode::~SectionNode() {}
CumulativeReporterBase::~CumulativeReporterBase() {}
BasicReporter::~BasicReporter() {}
StreamingReporterBase::~StreamingReporterBase() {}
@@ -84,7 +86,7 @@ namespace Catch {
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "basic", BasicReporter )
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "junit", JunitReporter )
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "junit2", JunitReporter2 )
}

View File

@@ -46,20 +46,6 @@ namespace Catch
bool shouldRedirectStdOut;
};
template<typename T, typename ChildT=T>
struct Node : SharedImpl<> {
Node( T const& _value, Node* _parent = NULL )
: value( _value ),
parent( _parent )
{}
virtual ~Node() {}
T value;
std::vector<Ptr<Node> > children;
Node* parent;
};
template<typename T>
struct LazyStat : Option<T> {
LazyStat() : used( false ) {}
@@ -238,8 +224,6 @@ namespace Catch
struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
typedef Ptr<Node<SectionInfo> > SectionInfoNode;
StreamingReporterBase( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
stream( _config.stream() )
@@ -260,8 +244,7 @@ namespace Catch
currentTestCaseInfo = _testInfo;
}
virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
Ptr<Node<SectionInfo> > sectionInfo = new Node<SectionInfo>( _sectionInfo );
m_sectionStack.push_back( sectionInfo );
m_sectionStack.push_back( _sectionInfo );
}
virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
@@ -281,30 +264,137 @@ namespace Catch
}
Ptr<IConfig> m_config;
std::ostream& stream;
LazyStat<TestRunInfo> currentTestRunInfo;
LazyStat<GroupInfo> currentGroupInfo;
LazyStat<TestCaseInfo> currentTestCaseInfo;
std::ostream& stream;
std::vector<SectionInfoNode> m_sectionStack;
std::vector<SectionInfo> m_sectionStack;
};
struct CumulativeReporterBase : StreamingReporterBase {
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
template<typename T, typename ChildNodeT>
struct Node : SharedImpl<> {
explicit Node( T const& _value ) : value( _value ) {}
virtual ~Node() {}
virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
T value;
ChildNodes children;
};
struct SectionNode : SharedImpl<> {
explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
virtual ~SectionNode();
virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
bool operator == ( SectionNode const& other ) const {
return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
}
bool operator == ( Ptr<SectionNode> const& other ) const {
return operator==( *other );
}
virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
SectionStats stats;
typedef std::vector<Ptr<SectionNode> > ChildSections;
typedef std::vector<AssertionStats> Assertions;
ChildSections childSections;
Assertions assertions;
std::string stdOut;
std::string stdErr;
};
friend bool operator == ( Ptr<SectionNode> const& node, SectionInfo const& other ) {
return node->stats.sectionInfo.lineInfo == other.lineInfo;
}
typedef Node<TestCaseStats, SectionNode> TestCaseNode;
typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
typedef Node<TestRunStats, TestGroupNode> TestRunNode;
CumulativeReporterBase( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
stream( _config.stream() )
{}
~CumulativeReporterBase();
virtual void testRunStarting( TestRunInfo const& ) {}
virtual void testGroupStarting( GroupInfo const& ) {}
virtual void testCaseStarting( TestCaseInfo const& ) {}
virtual void sectionStarting( SectionInfo const& sectionInfo ) {
SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
Ptr<SectionNode> node;
if( m_sectionStack.empty() ) {
if( !m_rootSection )
m_rootSection = new SectionNode( incompleteStats );
node = m_rootSection;
}
else {
SectionNode& parentNode = *m_sectionStack.back();
SectionNode::ChildSections::const_iterator it =
std::find( parentNode.childSections.begin(), parentNode.childSections.end(), sectionInfo );
if( it == parentNode.childSections.end() ) {
node = new SectionNode( incompleteStats );
parentNode.childSections.push_back( node );
}
else
node = *it;
}
m_sectionStack.push_back( node );
m_deepestSection = node;
}
virtual void assertionStarting( AssertionInfo const& ) {}
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
assert( !m_sectionStack.empty() );
SectionNode& sectionNode = *m_sectionStack.back();
sectionNode.assertions.push_back( assertionStats );
return true;
}
virtual void sectionEnded( SectionStats const& sectionStats ) {
assert( !m_sectionStack.empty() );
SectionNode& node = *m_sectionStack.back();
node.stats = sectionStats;
m_sectionStack.pop_back();
}
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
Ptr<TestCaseNode> node = new 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 ) {
Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
node->children.swap( m_testCases );
m_testGroups.push_back( node );
}
virtual void testRunEnded( TestRunStats const& testRunStats ) {
Ptr<TestRunNode> node = new TestRunNode( testRunStats );
node->children.swap( m_testGroups );
m_testRuns.push_back( node );
testRunEnded();
}
virtual void testRunEnded() = 0;
Ptr<IConfig> m_config;
std::ostream& stream;
std::vector<AssertionStats> m_assertions;
std::vector<std::vector<Ptr<SectionNode> > > m_sections;
std::vector<Ptr<TestCaseNode> > m_testCases;
std::vector<Ptr<TestGroupNode> > m_testGroups;
std::vector<Ptr<TestRunNode> > m_testRuns;
Ptr<SectionNode> m_rootSection;
Ptr<SectionNode> m_deepestSection;
std::vector<Ptr<SectionNode> > m_sectionStack;
std::vector<Ptr<Node<TestGroupStats> > > m_groups;
};
// Deprecated

View File

@@ -127,7 +127,7 @@ namespace Catch {
AutoReg::AutoReg( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc ) {
registerTestCase( new FreeFunctionTestCase( function ), "global", nameAndDesc, lineInfo );
registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
}
AutoReg::~AutoReg() {}

View File

@@ -174,9 +174,17 @@ inline std::string toString( unsigned int value ) {
inline std::string toString( const double value ) {
std::ostringstream oss;
oss << std::setprecision (std::numeric_limits<double>::digits10 + 1)
oss << std::setprecision( 10 )
<< std::fixed
<< value;
return oss.str();
std::string d = oss.str();
std::size_t i = d.find_last_not_of( '0' );
if( i != std::string::npos && i != d.size()-1 ) {
if( d[i] == '.' )
i++;
d = d.substr( 0, i+1 );
}
return d;
}
inline std::string toString( bool value ) {