Provide JunitReporter declaration with EXTERNAL_INTERFACES

Related to #991
This commit is contained in:
Martin Hořeňovský 2017-11-14 17:12:51 +01:00
parent 6acdacfde0
commit 4b3730de8a
4 changed files with 233 additions and 179 deletions

View File

@ -248,6 +248,7 @@ set(REPORTER_HEADERS
${HEADER_DIR}/reporters/catch_reporter_automake.hpp ${HEADER_DIR}/reporters/catch_reporter_automake.hpp
${HEADER_DIR}/reporters/catch_reporter_bases.hpp ${HEADER_DIR}/reporters/catch_reporter_bases.hpp
${HEADER_DIR}/reporters/catch_reporter_compact.h ${HEADER_DIR}/reporters/catch_reporter_compact.h
${HEADER_DIR}/reporters/catch_reporter_junit.h
${HEADER_DIR}/reporters/catch_reporter_multi.h ${HEADER_DIR}/reporters/catch_reporter_multi.h
${HEADER_DIR}/reporters/catch_reporter_tap.hpp ${HEADER_DIR}/reporters/catch_reporter_tap.hpp
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp ${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp

View File

@ -13,5 +13,6 @@
// Allow users to base their work off existing reporters // Allow users to base their work off existing reporters
#include "../reporters/catch_reporter_compact.h" #include "../reporters/catch_reporter_compact.h"
#include "../reporters/catch_reporter_junit.h"
#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED #endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED

View File

@ -8,10 +8,10 @@
#include "catch_reporter_bases.hpp" #include "catch_reporter_bases.hpp"
#include "catch_reporter_junit.h"
#include "../internal/catch_tostring.h" #include "../internal/catch_tostring.h"
#include "../internal/catch_reporter_registrars.hpp" #include "../internal/catch_reporter_registrars.hpp"
#include "internal/catch_xmlwriter.h"
#include "../internal/catch_timer.h"
#include <assert.h> #include <assert.h>
#include <sstream> #include <sstream>
@ -55,64 +55,63 @@ namespace Catch {
return it->substr(1); return it->substr(1);
return std::string(); return std::string();
} }
} } // anonymous namespace
class JunitReporter : public CumulativeReporterBase<JunitReporter> { JunitReporter::JunitReporter( ReporterConfig const& _config )
public:
JunitReporter( ReporterConfig const& _config )
: CumulativeReporterBase( _config ), : CumulativeReporterBase( _config ),
xml( _config.stream() ) xml( _config.stream() )
{ {
m_reporterPrefs.shouldRedirectStdOut = true; m_reporterPrefs.shouldRedirectStdOut = true;
} }
~JunitReporter() override; JunitReporter::~JunitReporter() {};
static std::string getDescription() { std::string JunitReporter::getDescription() {
return "Reports test results in an XML format that looks like Ant's junitreport target"; return "Reports test results in an XML format that looks like Ant's junitreport target";
} }
void noMatchingTestCases( std::string const& /*spec*/ ) override {} void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {}
void testRunStarting( TestRunInfo const& runInfo ) override { void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) {
CumulativeReporterBase::testRunStarting( runInfo ); CumulativeReporterBase::testRunStarting( runInfo );
xml.startElement( "testsuites" ); xml.startElement( "testsuites" );
} }
void testGroupStarting( GroupInfo const& groupInfo ) override { void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
suiteTimer.start(); suiteTimer.start();
stdOutForSuite.str(""); stdOutForSuite.clear();
stdErrForSuite.str(""); stdErrForSuite.clear();
unexpectedExceptions = 0; unexpectedExceptions = 0;
CumulativeReporterBase::testGroupStarting( groupInfo ); CumulativeReporterBase::testGroupStarting( groupInfo );
} }
void testCaseStarting( TestCaseInfo const& testCaseInfo ) override { void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {
m_okToFail = testCaseInfo.okToFail(); m_okToFail = testCaseInfo.okToFail();
} }
bool assertionEnded( AssertionStats const& assertionStats ) override {
bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {
if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
unexpectedExceptions++; unexpectedExceptions++;
return CumulativeReporterBase::assertionEnded( assertionStats ); return CumulativeReporterBase::assertionEnded( assertionStats );
} }
void testCaseEnded( TestCaseStats const& testCaseStats ) override { void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
stdOutForSuite << testCaseStats.stdOut; stdOutForSuite += testCaseStats.stdOut;
stdErrForSuite << testCaseStats.stdErr; stdErrForSuite += testCaseStats.stdErr;
CumulativeReporterBase::testCaseEnded( testCaseStats ); CumulativeReporterBase::testCaseEnded( testCaseStats );
} }
void testGroupEnded( TestGroupStats const& testGroupStats ) override { void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
double suiteTime = suiteTimer.getElapsedSeconds(); double suiteTime = suiteTimer.getElapsedSeconds();
CumulativeReporterBase::testGroupEnded( testGroupStats ); CumulativeReporterBase::testGroupEnded( testGroupStats );
writeGroup( *m_testGroups.back(), suiteTime ); writeGroup( *m_testGroups.back(), suiteTime );
} }
void testRunEndedCumulative() override { void JunitReporter::testRunEndedCumulative() {
xml.endElement(); xml.endElement();
} }
void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
TestGroupStats const& stats = groupNode.value; TestGroupStats const& stats = groupNode.value;
xml.writeAttribute( "name", stats.groupInfo.name ); xml.writeAttribute( "name", stats.groupInfo.name );
@ -130,11 +129,11 @@ namespace Catch {
for( auto const& child : groupNode.children ) for( auto const& child : groupNode.children )
writeTestCase( *child ); writeTestCase( *child );
xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false );
xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false );
} }
void writeTestCase( TestCaseNode const& testCaseNode ) { void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
TestCaseStats const& stats = testCaseNode.value; TestCaseStats const& stats = testCaseNode.value;
// All test cases have exactly one section - which represents the // All test cases have exactly one section - which represents the
@ -156,7 +155,7 @@ namespace Catch {
writeSection( className, "", rootSection ); writeSection( className, "", rootSection );
} }
void writeSection( std::string const& className, void JunitReporter::writeSection( std::string const& className,
std::string const& rootName, std::string const& rootName,
SectionNode const& sectionNode ) { SectionNode const& sectionNode ) {
std::string name = trim( sectionNode.stats.sectionInfo.name ); std::string name = trim( sectionNode.stats.sectionInfo.name );
@ -191,11 +190,12 @@ namespace Catch {
writeSection( className, name, *childNode ); writeSection( className, name, *childNode );
} }
void writeAssertions( SectionNode const& sectionNode ) { void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
for( auto const& assertion : sectionNode.assertions ) for( auto const& assertion : sectionNode.assertions )
writeAssertion( assertion ); writeAssertion( assertion );
} }
void writeAssertion( AssertionStats const& stats ) {
void JunitReporter::writeAssertion( AssertionStats const& stats ) {
AssertionResult const& result = stats.assertionResult; AssertionResult const& result = stats.assertionResult;
if( !result.isOk() ) { if( !result.isOk() ) {
std::string elementName; std::string elementName;
@ -242,15 +242,6 @@ namespace Catch {
} }
} }
XmlWriter xml;
Timer suiteTimer;
std::ostringstream stdOutForSuite;
std::ostringstream stdErrForSuite;
unsigned int unexpectedExceptions = 0;
bool m_okToFail = false;
};
JunitReporter::~JunitReporter() {}
CATCH_REGISTER_REPORTER( "junit", JunitReporter ) CATCH_REGISTER_REPORTER( "junit", JunitReporter )
} // end namespace Catch } // end namespace Catch

View File

@ -0,0 +1,61 @@
/*
* Created by Martin on 14/11/2017.
*
* 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_JUNIT_H_INCLUDED
#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_H_INCLUDED
#include "catch_reporter_bases.hpp"
#include "../internal/catch_xmlwriter.h"
#include "../internal/catch_timer.h"
namespace Catch {
class JunitReporter : public CumulativeReporterBase<JunitReporter> {
public:
JunitReporter(ReporterConfig const& _config);
~JunitReporter() override;
static std::string getDescription();
void noMatchingTestCases(std::string const& /*spec*/) override;
void testRunStarting(TestRunInfo const& runInfo) override;
void testGroupStarting(GroupInfo const& groupInfo) override;
void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
bool assertionEnded(AssertionStats const& assertionStats) override;
void testCaseEnded(TestCaseStats const& testCaseStats) override;
void testGroupEnded(TestGroupStats const& testGroupStats) override;
void testRunEndedCumulative() override;
void writeGroup(TestGroupNode const& groupNode, double suiteTime);
void writeTestCase(TestCaseNode const& testCaseNode);
void writeSection(std::string const& className,
std::string const& rootName,
SectionNode const& sectionNode);
void writeAssertions(SectionNode const& sectionNode);
void writeAssertion(AssertionStats const& stats);
XmlWriter xml;
Timer suiteTimer;
std::string stdOutForSuite;
std::string stdErrForSuite;
unsigned int unexpectedExceptions = 0;
bool m_okToFail = false;
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_REPORTER_JUNIT_H_INCLUDED