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_reporter_registry.hpp"
|
||||
#include "internal/catch_xmlwriter.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace Catch
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include "internal/catch_capture.hpp"
|
||||
#include "internal/catch_reporter_registry.hpp"
|
||||
#include <iostream>
|
||||
#include "internal/catch_xmlwriter.hpp"
|
||||
|
||||
namespace Catch
|
||||
{
|
||||
@ -35,19 +35,58 @@ namespace Catch
|
||||
|
||||
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 )
|
||||
{
|
||||
m_config.stream() << "<TestCase name='" << testInfo.getName() << "'>\n";
|
||||
m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
|
||||
m_currentTestSuccess = true;
|
||||
}
|
||||
|
||||
@ -59,47 +98,54 @@ namespace Catch
|
||||
|
||||
if( resultInfo.hasExpression() )
|
||||
{
|
||||
m_config.stream() << "\t<Expression success='" << (resultInfo.ok() ? "true" : "false") << "' "
|
||||
<< "filename='" << resultInfo.getFilename() << "' line='" << resultInfo.getLine() << "'>\n"
|
||||
<< "\t\t<Original>" << resultInfo.getExpression() << "</Original>\n"
|
||||
<< "\t\t<Expanded>" << resultInfo.getExpandedExpression() << "</Expanded>\n";
|
||||
m_xml.startElement( "Expression" )
|
||||
.writeAttribute( "success", resultInfo.ok() )
|
||||
.writeAttribute( "filename", resultInfo.getFilename() )
|
||||
.writeAttribute( "line", resultInfo.getLine() );
|
||||
|
||||
m_xml.scopedElement( "Original" )
|
||||
.writeText( resultInfo.getExpression() );
|
||||
m_xml.scopedElement( "Expanded" )
|
||||
.writeText( resultInfo.getExpandedExpression() );
|
||||
m_currentTestSuccess |= resultInfo.ok();
|
||||
}
|
||||
|
||||
switch( resultInfo.getResultType() )
|
||||
{
|
||||
case ResultWas::ThrewException:
|
||||
if( resultInfo.hasExpression() )
|
||||
m_config.stream() << "\t";
|
||||
m_config.stream() << "\t<Exception>" << resultInfo.getMessage() << "</Exception>\n";
|
||||
m_xml.scopedElement( "Exception" )
|
||||
.writeText( resultInfo.getMessage() );
|
||||
m_currentTestSuccess = false;
|
||||
break;
|
||||
case ResultWas::Info:
|
||||
m_config.stream() << "\t<Info>" << resultInfo.getMessage() << "</Info>\n";
|
||||
m_xml.scopedElement( "Info" )
|
||||
.writeText( resultInfo.getMessage() );
|
||||
break;
|
||||
case ResultWas::Warning:
|
||||
m_config.stream() << "\t<Warning>" << resultInfo.getMessage() << "</Warning>\n";
|
||||
m_xml.scopedElement( "Warning" )
|
||||
.writeText( resultInfo.getMessage() );
|
||||
break;
|
||||
case ResultWas::ExplicitFailure:
|
||||
m_config.stream() << "\t<Failure>" << resultInfo.getMessage() << "</Failure>\n";
|
||||
m_xml.scopedElement( "Failure" )
|
||||
.writeText( resultInfo.getMessage() );
|
||||
m_currentTestSuccess = false;
|
||||
break;
|
||||
}
|
||||
if( resultInfo.hasExpression() )
|
||||
{
|
||||
m_config.stream() << "\t</Expression>\n";
|
||||
}
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
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_config.stream() << "</TestCase>" << std::endl;
|
||||
m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
||||
private:
|
||||
const ReporterConfig& m_config;
|
||||
bool m_currentTestSuccess;
|
||||
XmlWriter m_xml;
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
@ -11,6 +11,10 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Catch
|
||||
{
|
||||
class XmlWriter
|
||||
@ -42,15 +46,28 @@ namespace Catch
|
||||
m_writer->writeText( text );
|
||||
return *this;
|
||||
}
|
||||
template<typename T>
|
||||
ScopedElement& writeAttribute( const std::string& name, const T& attribute )
|
||||
{
|
||||
m_writer->writeAttribute( name, attribute );
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable XmlWriter* m_writer;
|
||||
};
|
||||
|
||||
XmlWriter()
|
||||
: m_tagIsOpen( false ),
|
||||
m_needsNewline( false ),
|
||||
m_os( &std::cout )
|
||||
{
|
||||
}
|
||||
|
||||
XmlWriter( std::ostream& os)
|
||||
: m_tagIsOpen( false ),
|
||||
m_needsNewline( false ),
|
||||
m_os( os )
|
||||
m_os( &os )
|
||||
{
|
||||
}
|
||||
|
||||
@ -61,12 +78,28 @@ namespace Catch
|
||||
endElement();
|
||||
}
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
ensureTagClosed();
|
||||
newlineIfNecessary();
|
||||
m_os << m_indent << "<" << name;
|
||||
stream() << m_indent << "<" << name;
|
||||
m_tags.push_back( name );
|
||||
m_indent += " ";
|
||||
m_tagIsOpen = true;
|
||||
@ -86,12 +119,12 @@ namespace Catch
|
||||
m_indent = m_indent.substr( 0, m_indent.size()-2 );
|
||||
if( m_tagIsOpen )
|
||||
{
|
||||
m_os << "/>\n";
|
||||
stream() << "/>\n";
|
||||
m_tagIsOpen = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_os << m_indent << "</" << m_tags.back() << ">\n";
|
||||
stream() << m_indent << "</" << m_tags.back() << ">\n";
|
||||
}
|
||||
m_tags.pop_back();
|
||||
return *this;
|
||||
@ -101,19 +134,24 @@ namespace Catch
|
||||
{
|
||||
if( !name.empty() && !attribute.empty() )
|
||||
{
|
||||
m_os << " " << name << "=\"";
|
||||
stream() << " " << name << "=\"";
|
||||
writeEncodedText( attribute );
|
||||
m_os << "\"";
|
||||
stream() << "\"";
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
XmlWriter& writeAttribute( const std::string& name, bool attribute )
|
||||
{
|
||||
stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
XmlWriter& writeAttribute( const std::string& name, const T& attribute )
|
||||
{
|
||||
if( !name.empty() )
|
||||
{
|
||||
m_os << " " << name << "=\"" << attribute << "\"";
|
||||
stream() << " " << name << "=\"" << attribute << "\"";
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -125,7 +163,7 @@ namespace Catch
|
||||
bool tagWasOpen = m_tagIsOpen;
|
||||
ensureTagClosed();
|
||||
if( tagWasOpen )
|
||||
m_os << m_indent;
|
||||
stream() << m_indent;
|
||||
writeEncodedText( text );
|
||||
m_needsNewline = true;
|
||||
}
|
||||
@ -135,7 +173,7 @@ namespace Catch
|
||||
XmlWriter& writeComment( const std::string& text )
|
||||
{
|
||||
ensureTagClosed();
|
||||
m_os << m_indent << "<!--" << text << "-->";
|
||||
stream() << m_indent << "<!--" << text << "-->";
|
||||
m_needsNewline = true;
|
||||
return *this;
|
||||
}
|
||||
@ -143,17 +181,22 @@ namespace Catch
|
||||
XmlWriter& writeBlankLine()
|
||||
{
|
||||
ensureTagClosed();
|
||||
m_os << "\n";
|
||||
stream() << "\n";
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::ostream& stream()
|
||||
{
|
||||
return *m_os;
|
||||
}
|
||||
|
||||
void ensureTagClosed()
|
||||
{
|
||||
if( m_tagIsOpen )
|
||||
{
|
||||
m_os << ">\n";
|
||||
stream() << ">\n";
|
||||
m_tagIsOpen = false;
|
||||
}
|
||||
}
|
||||
@ -162,7 +205,7 @@ namespace Catch
|
||||
{
|
||||
if( m_needsNewline )
|
||||
{
|
||||
m_os << "\n";
|
||||
stream() << "\n";
|
||||
m_needsNewline = false;
|
||||
}
|
||||
}
|
||||
@ -174,7 +217,7 @@ namespace Catch
|
||||
!findReplaceableString( text, "&", "&" ) &&
|
||||
!findReplaceableString( text, "\"", ""e;" ) )
|
||||
{
|
||||
m_os << text;
|
||||
stream() << text;
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,7 +226,7 @@ namespace Catch
|
||||
std::string::size_type pos = text.find_first_of( replaceWhat );
|
||||
if( pos != std::string::npos )
|
||||
{
|
||||
m_os << text.substr( 0, pos ) << replaceWith;
|
||||
stream() << text.substr( 0, pos ) << replaceWith;
|
||||
writeEncodedText( text.substr( pos+1 ) );
|
||||
return true;
|
||||
}
|
||||
@ -194,7 +237,7 @@ namespace Catch
|
||||
bool m_needsNewline;
|
||||
std::vector<std::string> m_tags;
|
||||
std::string m_indent;
|
||||
std::ostream& m_os;
|
||||
std::ostream* m_os;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user