| /* |
| * Created by Phil on 28/10/2010. |
| * Copyright 2010 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) |
| */ |
| |
| #include "catch_reporter_xml.h" |
| |
| #include "../internal/catch_capture.hpp" |
| #include "../internal/catch_reporter_registrars.hpp" |
| |
| #if defined(_MSC_VER) |
| #pragma warning(push) |
| #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch |
| // Note that 4062 (not all labels are handled |
| // and default is missing) is enabled |
| #endif |
| |
| namespace Catch { |
| XmlReporter::XmlReporter( ReporterConfig const& _config ) |
| : StreamingReporterBase( _config ), |
| m_xml(_config.stream()) |
| { |
| m_reporterPrefs.shouldRedirectStdOut = true; |
| m_reporterPrefs.shouldReportAllAssertions = true; |
| } |
| |
| XmlReporter::~XmlReporter() = default; |
| |
| std::string XmlReporter::getDescription() { |
| return "Reports test results as an XML document"; |
| } |
| |
| std::string XmlReporter::getStylesheetRef() const { |
| return std::string(); |
| } |
| |
| void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) { |
| m_xml |
| .writeAttribute( "filename", sourceInfo.file ) |
| .writeAttribute( "line", sourceInfo.line ); |
| } |
| |
| void XmlReporter::noMatchingTestCases( std::string const& s ) { |
| StreamingReporterBase::noMatchingTestCases( s ); |
| } |
| |
| void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) { |
| StreamingReporterBase::testRunStarting( testInfo ); |
| std::string stylesheetRef = getStylesheetRef(); |
| if( !stylesheetRef.empty() ) |
| m_xml.writeStylesheetRef( stylesheetRef ); |
| m_xml.startElement( "Catch" ); |
| if( !m_config->name().empty() ) |
| m_xml.writeAttribute( "name", m_config->name() ); |
| if (m_config->testSpec().hasFilters()) |
| m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) ); |
| if( m_config->rngSeed() != 0 ) |
| m_xml.scopedElement( "Randomness" ) |
| .writeAttribute( "seed", m_config->rngSeed() ); |
| } |
| |
| void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) { |
| StreamingReporterBase::testGroupStarting( groupInfo ); |
| m_xml.startElement( "Group" ) |
| .writeAttribute( "name", groupInfo.name ); |
| } |
| |
| void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { |
| StreamingReporterBase::testCaseStarting(testInfo); |
| m_xml.startElement( "TestCase" ) |
| .writeAttribute( "name", trim( testInfo.name ) ) |
| .writeAttribute( "description", testInfo.description ) |
| .writeAttribute( "tags", testInfo.tagsAsString() ); |
| |
| writeSourceInfo( testInfo.lineInfo ); |
| |
| if ( m_config->showDurations() == ShowDurations::Always ) |
| m_testCaseTimer.start(); |
| m_xml.ensureTagClosed(); |
| } |
| |
| void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) { |
| StreamingReporterBase::sectionStarting( sectionInfo ); |
| if( m_sectionDepth++ > 0 ) { |
| m_xml.startElement( "Section" ) |
| .writeAttribute( "name", trim( sectionInfo.name ) ); |
| writeSourceInfo( sectionInfo.lineInfo ); |
| m_xml.ensureTagClosed(); |
| } |
| } |
| |
| void XmlReporter::assertionStarting( AssertionInfo const& ) { } |
| |
| bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) { |
| |
| AssertionResult const& result = assertionStats.assertionResult; |
| |
| bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); |
| |
| if( includeResults || result.getResultType() == ResultWas::Warning ) { |
| // Print any info messages in <Info> tags. |
| for( auto const& msg : assertionStats.infoMessages ) { |
| if( msg.type == ResultWas::Info && includeResults ) { |
| m_xml.scopedElement( "Info" ) |
| .writeText( msg.message ); |
| } else if ( msg.type == ResultWas::Warning ) { |
| m_xml.scopedElement( "Warning" ) |
| .writeText( msg.message ); |
| } |
| } |
| } |
| |
| // Drop out if result was successful but we're not printing them. |
| if( !includeResults && result.getResultType() != ResultWas::Warning ) |
| return true; |
| |
| |
| // Print the expression if there is one. |
| if( result.hasExpression() ) { |
| m_xml.startElement( "Expression" ) |
| .writeAttribute( "success", result.succeeded() ) |
| .writeAttribute( "type", result.getTestMacroName() ); |
| |
| writeSourceInfo( result.getSourceInfo() ); |
| |
| m_xml.scopedElement( "Original" ) |
| .writeText( result.getExpression() ); |
| m_xml.scopedElement( "Expanded" ) |
| .writeText( result.getExpandedExpression() ); |
| } |
| |
| // And... Print a result applicable to each result type. |
| switch( result.getResultType() ) { |
| case ResultWas::ThrewException: |
| m_xml.startElement( "Exception" ); |
| writeSourceInfo( result.getSourceInfo() ); |
| m_xml.writeText( result.getMessage() ); |
| m_xml.endElement(); |
| break; |
| case ResultWas::FatalErrorCondition: |
| m_xml.startElement( "FatalErrorCondition" ); |
| writeSourceInfo( result.getSourceInfo() ); |
| m_xml.writeText( result.getMessage() ); |
| m_xml.endElement(); |
| break; |
| case ResultWas::Info: |
| m_xml.scopedElement( "Info" ) |
| .writeText( result.getMessage() ); |
| break; |
| case ResultWas::Warning: |
| // Warning will already have been written |
| break; |
| case ResultWas::ExplicitFailure: |
| m_xml.startElement( "Failure" ); |
| writeSourceInfo( result.getSourceInfo() ); |
| m_xml.writeText( result.getMessage() ); |
| m_xml.endElement(); |
| break; |
| default: |
| break; |
| } |
| |
| if( result.hasExpression() ) |
| m_xml.endElement(); |
| |
| return true; |
| } |
| |
| void XmlReporter::sectionEnded( SectionStats const& sectionStats ) { |
| StreamingReporterBase::sectionEnded( sectionStats ); |
| if( --m_sectionDepth > 0 ) { |
| XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); |
| e.writeAttribute( "successes", sectionStats.assertions.passed ); |
| e.writeAttribute( "failures", sectionStats.assertions.failed ); |
| e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); |
| |
| if ( m_config->showDurations() == ShowDurations::Always ) |
| e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); |
| |
| m_xml.endElement(); |
| } |
| } |
| |
| void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { |
| StreamingReporterBase::testCaseEnded( testCaseStats ); |
| XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); |
| e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); |
| |
| if ( m_config->showDurations() == ShowDurations::Always ) |
| e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); |
| |
| if( !testCaseStats.stdOut.empty() ) |
| m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); |
| if( !testCaseStats.stdErr.empty() ) |
| m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); |
| |
| m_xml.endElement(); |
| } |
| |
| void XmlReporter::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(); |
| } |
| |
| void XmlReporter::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(); |
| } |
| |
| CATCH_REGISTER_REPORTER( "xml", XmlReporter ) |
| |
| } // end namespace Catch |
| |
| #if defined(_MSC_VER) |
| #pragma warning(pop) |
| #endif |