Refactored xml reporter in terms of xmlwriter and filled out new events

This commit is contained in:
Phil Nash 2010-12-10 20:01:40 +00:00
parent a35e4b5670
commit 68eec929e4
3 changed files with 127 additions and 39 deletions

View File

@ -15,7 +15,6 @@
#include "internal/catch_capture.hpp"
#include "internal/catch_reporter_registry.hpp"
#include "internal/catch_xmlwriter.hpp"
#include <iostream>
namespace Catch
{

View File

@ -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

View File

@ -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, "&", "&amp;" ) &&
!findReplaceableString( text, "\"", "&quote;" ) )
{
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;
};
}