Move the xml reporter away from the deprecated IReporter interface.

This commit is contained in:
Sean D. Cline 2014-10-11 17:20:55 -04:00
parent a5dca3d370
commit b0e53a8ee0
2 changed files with 94 additions and 68 deletions

View File

@ -88,8 +88,6 @@ namespace Catch {
Matchers::Impl::StdString::EndsWith::~EndsWith() {} Matchers::Impl::StdString::EndsWith::~EndsWith() {}
void Config::dummy() {} void Config::dummy() {}
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
} }
#ifdef __clang__ #ifdef __clang__

View File

@ -15,78 +15,83 @@
#include "../internal/catch_xmlwriter.hpp" #include "../internal/catch_xmlwriter.hpp"
namespace Catch { namespace Catch {
class XmlReporter : public SharedImpl<IReporter> { class XmlReporter : public StreamingReporterBase {
public: public:
XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} XmlReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ),
m_sectionDepth( 0 )
{}
virtual ~XmlReporter();
static std::string getDescription() { static std::string getDescription() {
return "Reports test results as an XML document"; return "Reports test results as an XML document";
} }
virtual ~XmlReporter();
private: // IReporter public: // StreamingReporterBase
virtual ReporterPreferences getPreferences() const {
virtual bool shouldRedirectStdout() const { ReporterPreferences prefs;
return true; prefs.shouldRedirectStdOut = true;
return prefs;
} }
virtual void StartTesting() { virtual void noMatchingTestCases( std::string const& s ) {
m_xml.setStream( m_config.stream() ); StreamingReporterBase::noMatchingTestCases( s );
}
virtual void testRunStarting( TestRunInfo const& testInfo ) {
StreamingReporterBase::testRunStarting( testInfo );
m_xml.setStream( stream );
m_xml.startElement( "Catch" ); m_xml.startElement( "Catch" );
if( !m_config.fullConfig()->name().empty() ) if( !m_config->name().empty() )
m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); m_xml.writeAttribute( "name", m_config->name() );
} }
virtual void EndTesting( const Totals& totals ) { virtual void testGroupStarting( GroupInfo const& groupInfo ) {
m_xml.scopedElement( "OverallResults" ) StreamingReporterBase::testGroupStarting( groupInfo );
.writeAttribute( "successes", totals.assertions.passed )
.writeAttribute( "failures", totals.assertions.failed )
.writeAttribute( "expectedFailures", totals.assertions.failedButOk );
m_xml.endElement();
}
virtual void StartGroup( const std::string& groupName ) {
m_xml.startElement( "Group" ) m_xml.startElement( "Group" )
.writeAttribute( "name", groupName ); .writeAttribute( "name", groupInfo.name );
} }
virtual void EndGroup( const std::string&, const Totals& totals ) { virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
m_xml.scopedElement( "OverallResults" ) StreamingReporterBase::testCaseStarting(testInfo);
.writeAttribute( "successes", totals.assertions.passed ) m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
.writeAttribute( "failures", totals.assertions.failed )
.writeAttribute( "expectedFailures", totals.assertions.failedButOk );
m_xml.endElement();
} }
virtual void StartSection( const std::string& sectionName, const std::string& description ) { virtual void sectionStarting( SectionInfo const& sectionInfo ) {
StreamingReporterBase::sectionStarting( sectionInfo );
if( m_sectionDepth++ > 0 ) { if( m_sectionDepth++ > 0 ) {
m_xml.startElement( "Section" ) m_xml.startElement( "Section" )
.writeAttribute( "name", trim( sectionName ) ) .writeAttribute( "name", trim( sectionInfo.name ) )
.writeAttribute( "description", description ); .writeAttribute( "description", sectionInfo.description );
}
}
virtual void NoAssertionsInSection( const std::string& ) {}
virtual void NoAssertionsInTestCase( const std::string& ) {}
virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
if( --m_sectionDepth > 0 ) {
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", assertions.passed )
.writeAttribute( "failures", assertions.failed )
.writeAttribute( "expectedFailures", assertions.failedButOk );
m_xml.endElement();
} }
} }
virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { virtual void assertionStarting( AssertionInfo const& ) { }
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
m_currentTestSuccess = true;
}
virtual void Result( const Catch::AssertionResult& assertionResult ) { virtual bool assertionEnded( AssertionStats const& assertionStats ) {
if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) const AssertionResult& assertionResult = assertionStats.assertionResult;
return;
// Print any info messages in <Info> tags.
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
it != itEnd;
++it ) {
if( it->type == ResultWas::Info ) {
m_xml.scopedElement( "Info" )
.writeText( it->message );
} else if ( it->type == ResultWas::Warning ) {
m_xml.scopedElement( "Warning" )
.writeText( it->message );
}
}
}
// Drop out if result was successful but we're not printing them.
if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
return true;
// Print the expression if there is one.
if( assertionResult.hasExpression() ) { if( assertionResult.hasExpression() ) {
m_xml.startElement( "Expression" ) m_xml.startElement( "Expression" )
.writeAttribute( "success", assertionResult.succeeded() ) .writeAttribute( "success", assertionResult.succeeded() )
@ -97,23 +102,23 @@ namespace Catch {
.writeText( assertionResult.getExpression() ); .writeText( assertionResult.getExpression() );
m_xml.scopedElement( "Expanded" ) m_xml.scopedElement( "Expanded" )
.writeText( assertionResult.getExpandedExpression() ); .writeText( assertionResult.getExpandedExpression() );
m_currentTestSuccess &= assertionResult.succeeded();
} }
// And... Print a result applicable to each result type.
switch( assertionResult.getResultType() ) { switch( assertionResult.getResultType() ) {
default:
break;
case ResultWas::ThrewException: case ResultWas::ThrewException:
m_xml.scopedElement( "Exception" ) m_xml.scopedElement( "Exception" )
.writeAttribute( "filename", assertionResult.getSourceInfo().file ) .writeAttribute( "filename", assertionResult.getSourceInfo().file )
.writeAttribute( "line", assertionResult.getSourceInfo().line ) .writeAttribute( "line", assertionResult.getSourceInfo().line )
.writeText( assertionResult.getMessage() ); .writeText( assertionResult.getMessage() );
m_currentTestSuccess = false;
break; break;
case ResultWas::FatalErrorCondition: case ResultWas::FatalErrorCondition:
m_xml.scopedElement( "Fatal Error Condition" ) m_xml.scopedElement( "Fatal Error Condition" )
.writeAttribute( "filename", assertionResult.getSourceInfo().file ) .writeAttribute( "filename", assertionResult.getSourceInfo().file )
.writeAttribute( "line", assertionResult.getSourceInfo().line ) .writeAttribute( "line", assertionResult.getSourceInfo().line )
.writeText( assertionResult.getMessage() ); .writeText( assertionResult.getMessage() );
m_currentTestSuccess = false;
break; break;
case ResultWas::Info: case ResultWas::Info:
m_xml.scopedElement( "Info" ) m_xml.scopedElement( "Info" )
@ -126,36 +131,59 @@ namespace Catch {
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
m_xml.scopedElement( "Failure" ) m_xml.scopedElement( "Failure" )
.writeText( assertionResult.getMessage() ); .writeText( assertionResult.getMessage() );
m_currentTestSuccess = false;
break;
case ResultWas::Unknown:
case ResultWas::Ok:
case ResultWas::FailureBit:
case ResultWas::ExpressionFailed:
case ResultWas::Exception:
case ResultWas::DidntThrowException:
break; break;
} }
if( assertionResult.hasExpression() ) if( assertionResult.hasExpression() )
m_xml.endElement(); m_xml.endElement();
return true;
} }
virtual void Aborted() { virtual void sectionEnded( SectionStats const& sectionStats ) {
// !TBD StreamingReporterBase::sectionEnded( sectionStats );
if( --m_sectionDepth > 0 ) {
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", sectionStats.assertions.passed )
.writeAttribute( "failures", sectionStats.assertions.failed )
.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
m_xml.endElement();
}
} }
virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); StreamingReporterBase::testCaseEnded( testCaseStats );
m_xml.scopedElement( "OverallResult" )
.writeAttribute( "success", testCaseStats.totals.assertions.allPassed() );
m_xml.endElement();
}
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
StreamingReporterBase::testGroupEnded( testGroupStats );
// TODO: Check testGroupStats.aborting and act accordingly.
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", testGroupStats.totals.assertions.passed )
.writeAttribute( "failures", testGroupStats.totals.assertions.failed )
.writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
m_xml.endElement();
}
virtual void testRunEnded( TestRunStats const& testRunStats ) {
StreamingReporterBase::testRunEnded( testRunStats );
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", testRunStats.totals.assertions.passed )
.writeAttribute( "failures", testRunStats.totals.assertions.failed )
.writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
m_xml.endElement(); m_xml.endElement();
} }
private: private:
ReporterConfig m_config;
bool m_currentTestSuccess;
XmlWriter m_xml; XmlWriter m_xml;
int m_sectionDepth; int m_sectionDepth;
}; };
INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
} // end namespace Catch } // end namespace Catch
#endif // TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED