mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-26 07:16:10 +01:00
Refactored xml reporter in terms of xmlwriter and filled out new events
This commit is contained in:
parent
a35e4b5670
commit
68eec929e4
@ -15,7 +15,6 @@
|
|||||||
#include "internal/catch_capture.hpp"
|
#include "internal/catch_capture.hpp"
|
||||||
#include "internal/catch_reporter_registry.hpp"
|
#include "internal/catch_reporter_registry.hpp"
|
||||||
#include "internal/catch_xmlwriter.hpp"
|
#include "internal/catch_xmlwriter.hpp"
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace Catch
|
namespace Catch
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include "internal/catch_capture.hpp"
|
#include "internal/catch_capture.hpp"
|
||||||
#include "internal/catch_reporter_registry.hpp"
|
#include "internal/catch_reporter_registry.hpp"
|
||||||
#include <iostream>
|
#include "internal/catch_xmlwriter.hpp"
|
||||||
|
|
||||||
namespace Catch
|
namespace Catch
|
||||||
{
|
{
|
||||||
@ -35,19 +35,58 @@ namespace Catch
|
|||||||
|
|
||||||
private: // ITestReporter
|
private: // ITestReporter
|
||||||
|
|
||||||
virtual void StartTesting(){}
|
///////////////////////////////////////////////////////////////////////////
|
||||||
virtual void EndTesting( std::size_t succeeded, std::size_t failed ){(succeeded, failed);}
|
virtual void StartTesting()
|
||||||
|
{
|
||||||
|
m_xml = XmlWriter( m_config.stream() );
|
||||||
|
m_xml.startElement( "AllTests" );
|
||||||
|
}
|
||||||
|
|
||||||
virtual void StartGroup( const std::string& groupName ){(groupName);}
|
///////////////////////////////////////////////////////////////////////////
|
||||||
virtual void EndGroup( const std::string& groupName, std::size_t succeeded, std::size_t failed ){(groupName, succeeded, failed);}
|
virtual void EndTesting( std::size_t succeeded, std::size_t failed )
|
||||||
|
{
|
||||||
|
m_xml.scopedElement( "OverallResults" )
|
||||||
|
.writeAttribute( "successes", succeeded )
|
||||||
|
.writeAttribute( "failures", failed );
|
||||||
|
}
|
||||||
|
|
||||||
virtual void StartSection( const std::string& sectionName, const std::string description ){(sectionName,description);}
|
///////////////////////////////////////////////////////////////////////////
|
||||||
virtual void EndSection( const std::string& sectionName, std::size_t succeeded, std::size_t failed ){(sectionName, succeeded, failed);}
|
virtual void StartGroup( const std::string& groupName )
|
||||||
|
{
|
||||||
|
m_xml.startElement( "Group" )
|
||||||
|
.writeAttribute( "name", groupName );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
virtual void EndGroup( const std::string& groupName, std::size_t succeeded, std::size_t failed )
|
||||||
|
{
|
||||||
|
m_xml.scopedElement( "OverallResults" )
|
||||||
|
.writeAttribute( "successes", succeeded )
|
||||||
|
.writeAttribute( "failures", failed );
|
||||||
|
m_xml.endElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
virtual void StartSection( const std::string& sectionName, const std::string description )
|
||||||
|
{
|
||||||
|
m_xml.startElement( "Section" )
|
||||||
|
.writeAttribute( "name", sectionName )
|
||||||
|
.writeAttribute( "description", description );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
virtual void EndSection( const std::string& sectionName, std::size_t succeeded, std::size_t failed )
|
||||||
|
{
|
||||||
|
m_xml.scopedElement( "OverallResults" )
|
||||||
|
.writeAttribute( "successes", succeeded )
|
||||||
|
.writeAttribute( "failures", failed );
|
||||||
|
m_xml.endElement();
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
|
virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
|
||||||
{
|
{
|
||||||
m_config.stream() << "<TestCase name='" << testInfo.getName() << "'>\n";
|
m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
|
||||||
m_currentTestSuccess = true;
|
m_currentTestSuccess = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,47 +98,54 @@ namespace Catch
|
|||||||
|
|
||||||
if( resultInfo.hasExpression() )
|
if( resultInfo.hasExpression() )
|
||||||
{
|
{
|
||||||
m_config.stream() << "\t<Expression success='" << (resultInfo.ok() ? "true" : "false") << "' "
|
m_xml.startElement( "Expression" )
|
||||||
<< "filename='" << resultInfo.getFilename() << "' line='" << resultInfo.getLine() << "'>\n"
|
.writeAttribute( "success", resultInfo.ok() )
|
||||||
<< "\t\t<Original>" << resultInfo.getExpression() << "</Original>\n"
|
.writeAttribute( "filename", resultInfo.getFilename() )
|
||||||
<< "\t\t<Expanded>" << resultInfo.getExpandedExpression() << "</Expanded>\n";
|
.writeAttribute( "line", resultInfo.getLine() );
|
||||||
|
|
||||||
|
m_xml.scopedElement( "Original" )
|
||||||
|
.writeText( resultInfo.getExpression() );
|
||||||
|
m_xml.scopedElement( "Expanded" )
|
||||||
|
.writeText( resultInfo.getExpandedExpression() );
|
||||||
m_currentTestSuccess |= resultInfo.ok();
|
m_currentTestSuccess |= resultInfo.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( resultInfo.getResultType() )
|
switch( resultInfo.getResultType() )
|
||||||
{
|
{
|
||||||
case ResultWas::ThrewException:
|
case ResultWas::ThrewException:
|
||||||
if( resultInfo.hasExpression() )
|
m_xml.scopedElement( "Exception" )
|
||||||
m_config.stream() << "\t";
|
.writeText( resultInfo.getMessage() );
|
||||||
m_config.stream() << "\t<Exception>" << resultInfo.getMessage() << "</Exception>\n";
|
|
||||||
m_currentTestSuccess = false;
|
m_currentTestSuccess = false;
|
||||||
break;
|
break;
|
||||||
case ResultWas::Info:
|
case ResultWas::Info:
|
||||||
m_config.stream() << "\t<Info>" << resultInfo.getMessage() << "</Info>\n";
|
m_xml.scopedElement( "Info" )
|
||||||
|
.writeText( resultInfo.getMessage() );
|
||||||
break;
|
break;
|
||||||
case ResultWas::Warning:
|
case ResultWas::Warning:
|
||||||
m_config.stream() << "\t<Warning>" << resultInfo.getMessage() << "</Warning>\n";
|
m_xml.scopedElement( "Warning" )
|
||||||
|
.writeText( resultInfo.getMessage() );
|
||||||
break;
|
break;
|
||||||
case ResultWas::ExplicitFailure:
|
case ResultWas::ExplicitFailure:
|
||||||
m_config.stream() << "\t<Failure>" << resultInfo.getMessage() << "</Failure>\n";
|
m_xml.scopedElement( "Failure" )
|
||||||
|
.writeText( resultInfo.getMessage() );
|
||||||
m_currentTestSuccess = false;
|
m_currentTestSuccess = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( resultInfo.hasExpression() )
|
if( resultInfo.hasExpression() )
|
||||||
{
|
m_xml.endElement();
|
||||||
m_config.stream() << "\t</Expression>\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
virtual void EndTestCase( const Catch::TestCaseInfo&, const std::string& stdOut, const std::string& stdErr )
|
virtual void EndTestCase( const Catch::TestCaseInfo&, const std::string& stdOut, const std::string& stdErr )
|
||||||
{
|
{
|
||||||
m_config.stream() << "\t<OverallResult success='" << (m_currentTestSuccess ? "true" : "false" ) << "/>\n";
|
m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
|
||||||
m_config.stream() << "</TestCase>" << std::endl;
|
m_xml.endElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ReporterConfig& m_config;
|
const ReporterConfig& m_config;
|
||||||
bool m_currentTestSuccess;
|
bool m_currentTestSuccess;
|
||||||
|
XmlWriter m_xml;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Catch
|
namespace Catch
|
||||||
{
|
{
|
||||||
class XmlWriter
|
class XmlWriter
|
||||||
@ -42,15 +46,28 @@ namespace Catch
|
|||||||
m_writer->writeText( text );
|
m_writer->writeText( text );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
template<typename T>
|
||||||
|
ScopedElement& writeAttribute( const std::string& name, const T& attribute )
|
||||||
|
{
|
||||||
|
m_writer->writeAttribute( name, attribute );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable XmlWriter* m_writer;
|
mutable XmlWriter* m_writer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
XmlWriter()
|
||||||
|
: m_tagIsOpen( false ),
|
||||||
|
m_needsNewline( false ),
|
||||||
|
m_os( &std::cout )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
XmlWriter( std::ostream& os)
|
XmlWriter( std::ostream& os)
|
||||||
: m_tagIsOpen( false ),
|
: m_tagIsOpen( false ),
|
||||||
m_needsNewline( false ),
|
m_needsNewline( false ),
|
||||||
m_os( os )
|
m_os( &os )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,11 +79,27 @@ namespace Catch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XmlWriter& operator = ( const XmlWriter& other )
|
||||||
|
{
|
||||||
|
XmlWriter temp( other );
|
||||||
|
swap( temp );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap( XmlWriter& other )
|
||||||
|
{
|
||||||
|
std::swap( m_tagIsOpen, other.m_tagIsOpen );
|
||||||
|
std::swap( m_needsNewline, other.m_needsNewline );
|
||||||
|
std::swap( m_tags, other.m_tags );
|
||||||
|
std::swap( m_indent, other.m_indent );
|
||||||
|
std::swap( m_os, other.m_os );
|
||||||
|
}
|
||||||
|
|
||||||
XmlWriter& startElement( const std::string& name )
|
XmlWriter& startElement( const std::string& name )
|
||||||
{
|
{
|
||||||
ensureTagClosed();
|
ensureTagClosed();
|
||||||
newlineIfNecessary();
|
newlineIfNecessary();
|
||||||
m_os << m_indent << "<" << name;
|
stream() << m_indent << "<" << name;
|
||||||
m_tags.push_back( name );
|
m_tags.push_back( name );
|
||||||
m_indent += " ";
|
m_indent += " ";
|
||||||
m_tagIsOpen = true;
|
m_tagIsOpen = true;
|
||||||
@ -86,12 +119,12 @@ namespace Catch
|
|||||||
m_indent = m_indent.substr( 0, m_indent.size()-2 );
|
m_indent = m_indent.substr( 0, m_indent.size()-2 );
|
||||||
if( m_tagIsOpen )
|
if( m_tagIsOpen )
|
||||||
{
|
{
|
||||||
m_os << "/>\n";
|
stream() << "/>\n";
|
||||||
m_tagIsOpen = false;
|
m_tagIsOpen = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_os << m_indent << "</" << m_tags.back() << ">\n";
|
stream() << m_indent << "</" << m_tags.back() << ">\n";
|
||||||
}
|
}
|
||||||
m_tags.pop_back();
|
m_tags.pop_back();
|
||||||
return *this;
|
return *this;
|
||||||
@ -101,19 +134,24 @@ namespace Catch
|
|||||||
{
|
{
|
||||||
if( !name.empty() && !attribute.empty() )
|
if( !name.empty() && !attribute.empty() )
|
||||||
{
|
{
|
||||||
m_os << " " << name << "=\"";
|
stream() << " " << name << "=\"";
|
||||||
writeEncodedText( attribute );
|
writeEncodedText( attribute );
|
||||||
m_os << "\"";
|
stream() << "\"";
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
XmlWriter& writeAttribute( const std::string& name, bool attribute )
|
||||||
|
{
|
||||||
|
stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
XmlWriter& writeAttribute( const std::string& name, const T& attribute )
|
XmlWriter& writeAttribute( const std::string& name, const T& attribute )
|
||||||
{
|
{
|
||||||
if( !name.empty() )
|
if( !name.empty() )
|
||||||
{
|
{
|
||||||
m_os << " " << name << "=\"" << attribute << "\"";
|
stream() << " " << name << "=\"" << attribute << "\"";
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -125,7 +163,7 @@ namespace Catch
|
|||||||
bool tagWasOpen = m_tagIsOpen;
|
bool tagWasOpen = m_tagIsOpen;
|
||||||
ensureTagClosed();
|
ensureTagClosed();
|
||||||
if( tagWasOpen )
|
if( tagWasOpen )
|
||||||
m_os << m_indent;
|
stream() << m_indent;
|
||||||
writeEncodedText( text );
|
writeEncodedText( text );
|
||||||
m_needsNewline = true;
|
m_needsNewline = true;
|
||||||
}
|
}
|
||||||
@ -135,7 +173,7 @@ namespace Catch
|
|||||||
XmlWriter& writeComment( const std::string& text )
|
XmlWriter& writeComment( const std::string& text )
|
||||||
{
|
{
|
||||||
ensureTagClosed();
|
ensureTagClosed();
|
||||||
m_os << m_indent << "<!--" << text << "-->";
|
stream() << m_indent << "<!--" << text << "-->";
|
||||||
m_needsNewline = true;
|
m_needsNewline = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -143,17 +181,22 @@ namespace Catch
|
|||||||
XmlWriter& writeBlankLine()
|
XmlWriter& writeBlankLine()
|
||||||
{
|
{
|
||||||
ensureTagClosed();
|
ensureTagClosed();
|
||||||
m_os << "\n";
|
stream() << "\n";
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
std::ostream& stream()
|
||||||
|
{
|
||||||
|
return *m_os;
|
||||||
|
}
|
||||||
|
|
||||||
void ensureTagClosed()
|
void ensureTagClosed()
|
||||||
{
|
{
|
||||||
if( m_tagIsOpen )
|
if( m_tagIsOpen )
|
||||||
{
|
{
|
||||||
m_os << ">\n";
|
stream() << ">\n";
|
||||||
m_tagIsOpen = false;
|
m_tagIsOpen = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +205,7 @@ namespace Catch
|
|||||||
{
|
{
|
||||||
if( m_needsNewline )
|
if( m_needsNewline )
|
||||||
{
|
{
|
||||||
m_os << "\n";
|
stream() << "\n";
|
||||||
m_needsNewline = false;
|
m_needsNewline = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,7 +217,7 @@ namespace Catch
|
|||||||
!findReplaceableString( text, "&", "&" ) &&
|
!findReplaceableString( text, "&", "&" ) &&
|
||||||
!findReplaceableString( text, "\"", ""e;" ) )
|
!findReplaceableString( text, "\"", ""e;" ) )
|
||||||
{
|
{
|
||||||
m_os << text;
|
stream() << text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +226,7 @@ namespace Catch
|
|||||||
std::string::size_type pos = text.find_first_of( replaceWhat );
|
std::string::size_type pos = text.find_first_of( replaceWhat );
|
||||||
if( pos != std::string::npos )
|
if( pos != std::string::npos )
|
||||||
{
|
{
|
||||||
m_os << text.substr( 0, pos ) << replaceWith;
|
stream() << text.substr( 0, pos ) << replaceWith;
|
||||||
writeEncodedText( text.substr( pos+1 ) );
|
writeEncodedText( text.substr( pos+1 ) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -194,7 +237,7 @@ namespace Catch
|
|||||||
bool m_needsNewline;
|
bool m_needsNewline;
|
||||||
std::vector<std::string> m_tags;
|
std::vector<std::string> m_tags;
|
||||||
std::string m_indent;
|
std::string m_indent;
|
||||||
std::ostream& m_os;
|
std::ostream* m_os;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user