Work in progress on Console reporter.

Includes regenerated single include for Obj-C fixes
This commit is contained in:
Phil Nash 2012-12-06 08:44:51 +00:00
parent 442463473d
commit ff03cdf2b2
4 changed files with 345 additions and 51 deletions

2
README
View File

@ -1,4 +1,4 @@
CATCH v0.9 build 8 (integration branch) CATCH v0.9 build 9 (integration branch)
--------------------------------------------- ---------------------------------------------
CATCH is an automated test framework for C, C++ and Objective-C. CATCH is an automated test framework for C, C++ and Objective-C.

View File

@ -13,7 +13,7 @@
namespace Catch { namespace Catch {
// These numbers are maintained by a script // These numbers are maintained by a script
Version libraryVersion( 0, 9, 8, "integration" ); Version libraryVersion( 0, 9, 9, "integration" );
} }
#endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED

View File

@ -35,28 +35,27 @@ namespace Catch {
} }
void lazyPrintGroupInfo() { void lazyPrintGroupInfo() {
if( !unusedGroupInfo->name.empty() ) if( !unusedGroupInfo->name.empty() )
stream << "[Group: " << unusedGroupInfo->name << "]" << std::endl; stream << "[Group: '" << unusedGroupInfo->name << "']" << std::endl;
unusedGroupInfo.reset(); unusedGroupInfo.reset();
} }
void lazyPrintTestCaseInfo() { void lazyPrintTestCaseInfo() {
stream << "[TestCase: " << unusedTestCaseInfo->name << "]" << std::endl; stream << "[Test case: '" << unusedTestCaseInfo->name << "']" << std::endl;
unusedTestCaseInfo.reset(); unusedTestCaseInfo.reset();
} }
std::string makeSectionPath( ThreadedSectionInfo const * section, std::string const& delimiter ) {
std::string sectionPath = "'" + section->name + "'";
while( ( section = section->parent.get() ) )
sectionPath = "'" + section->name + "'" + delimiter + sectionPath;
return sectionPath;
}
void lazyPrintSectionInfo() { void lazyPrintSectionInfo() {
ThreadedSectionInfo* section = unusedSectionInfo.get(); ThreadedSectionInfo* section = unusedSectionInfo.get();
bool firstSection = true;
stream << "[Section: ";
do {
if( firstSection )
firstSection = false;
else
stream << ",\n ";
stream << section->name;
section = section->parent.get();
}
while( section );
stream << "]" << std::endl; std::string sectionPath = makeSectionPath( section, ", " );
if( sectionPath.size() > 60 )
sectionPath = makeSectionPath( section, ",\n " );
stream << "[Section: " << sectionPath << "]" << std::endl;
unusedSectionInfo.reset(); unusedSectionInfo.reset();
} }
void lazyPrint() { void lazyPrint() {
@ -77,18 +76,58 @@ namespace Catch {
lazyPrint(); lazyPrint();
} }
void printAssertionCounts( std::string const& label, Counts const& counts, std::string const& allPrefix = "All " ) {
if( counts.passed )
stream << counts.failed << " of " << counts.total() << " " << label << "s failed";
else
stream << ( counts.failed > 1 ? allPrefix : "" ) << pluralise( counts.failed, label ) << " failed";
}
void printTotals( const Totals& totals, const std::string& allPrefix = "All " ) {
if( totals.assertions.total() == 0 ) {
stream << "No tests ran";
}
else if( totals.assertions.failed ) {
TextColour colour( TextColour::ResultError );
printAssertionCounts( "test case", totals.testCases, allPrefix );
if( totals.testCases.failed > 0 ) {
stream << " (";
printAssertionCounts( "assertion", totals.assertions, allPrefix );
stream << ")";
}
}
else {
TextColour colour( TextColour::ResultSuccess );
stream << allPrefix << "tests passed ("
<< pluralise( totals.assertions.passed, "assertion" ) << " in "
<< pluralise( totals.testCases.passed, "test case" ) << ")";
}
}
virtual void sectionEnded( Ptr<SectionStats const> const& _sectionStats ) { virtual void sectionEnded( Ptr<SectionStats const> const& _sectionStats ) {
if( !unusedSectionInfo ) { if( !unusedSectionInfo ) {
stream << "[Section totals: ]" << std::endl; stream << "[Summary for section '" << _sectionStats->sectionInfo.name << "': ";
printAssertionCounts( "assertion", _sectionStats->assertions );
stream << "]\n" << std::endl;
} }
AccumulatingReporter::sectionEnded( _sectionStats ); AccumulatingReporter::sectionEnded( _sectionStats );
} }
virtual void testCaseEnded( Ptr<TestCaseStats const> const& _testCaseStats ) { virtual void testCaseEnded( Ptr<TestCaseStats const> const& _testCaseStats ) {
if( !unusedTestCaseInfo ) { if( !unusedTestCaseInfo ) {
stream << "[TestCase totals: ]\n" << std::endl; stream << "[Summary for test case '" << _testCaseStats->testInfo.name << "': ";
printTotals( _testCaseStats->totals );
stream << "]\n" << std::endl;
} }
AccumulatingReporter::testCaseEnded( _testCaseStats ); AccumulatingReporter::testCaseEnded( _testCaseStats );
} }
virtual void testGroupEnded( Ptr<TestGroupStats const> const& _testGroupStats ) {
// !TBD
AccumulatingReporter::testGroupEnded( _testGroupStats );
}
virtual void testRunEnded( Ptr<TestRunStats const> const& _testRunStats ) {
// !TBD
AccumulatingReporter::testRunEnded( _testRunStats );
}
}; };

View File

@ -1,6 +1,6 @@
/* /*
* CATCH v0.9 build 8 (integration branch) * CATCH v0.9 build 9 (integration branch)
* Generated: 2012-12-02 00:05:11.160560 * Generated: 2012-12-06 08:42:33.813351
* ---------------------------------------------------------- * ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly * This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@ -274,6 +274,11 @@ namespace Catch {
if( m_p ) if( m_p )
m_p->release(); m_p->release();
} }
void reset() {
if( m_p )
m_p->release();
m_p = NULL;
}
Ptr& operator = ( T* p ){ Ptr& operator = ( T* p ){
Ptr temp( p ); Ptr temp( p );
swap( temp ); swap( temp );
@ -290,6 +295,7 @@ namespace Catch {
T& operator*() const { return *m_p; } T& operator*() const { return *m_p; }
T* operator->() const { return m_p; } T* operator->() const { return m_p; }
bool operator !() const { return m_p == NULL; } bool operator !() const { return m_p == NULL; }
operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
private: private:
T* m_p; T* m_p;
@ -1246,8 +1252,8 @@ namespace Catch {
std::string className; std::string className;
std::string description; std::string description;
std::set<std::string> tags; std::set<std::string> tags;
bool isHidden;
SourceLineInfo lineInfo; SourceLineInfo lineInfo;
bool isHidden;
}; };
class TestCase : protected TestCaseInfo { class TestCase : protected TestCaseInfo {
@ -1877,6 +1883,59 @@ namespace Catch {
} // end namespace Catch } // end namespace Catch
// #included from: catch_option.hpp
#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
namespace Catch {
// An optional type
template<typename T>
class Option {
public:
Option() : nullableValue( NULL ) {}
Option( T const& _value )
: nullableValue( new( storage ) T( _value ) )
{}
Option( Option const& _other )
: nullableValue( _other ? new( storage ) T( *_other ) : NULL )
{}
~Option() {
reset();
}
Option& operator= ( Option const& _other ) {
reset();
if( _other )
nullableValue = new( storage ) T( *_other );
return *this;
}
void reset() {
if( nullableValue )
nullableValue->~T();
nullableValue = NULL;
}
T& operator*() { return *nullableValue; }
const T& operator*() const { return *nullableValue; }
T* operator->() { return nullableValue; }
const T* operator->() const { return nullableValue; }
bool some() const { return nullableValue != NULL; }
bool none() const { return nullableValue == NULL; }
bool operator !() const { return nullableValue == NULL; }
operator SafeBool::type() const {
return SafeBool::makeSafe( some() );
}
private:
T* nullableValue;
char storage[sizeof(T)];
};
} // end namespace Catch
#include <string> #include <string>
#include <ostream> #include <ostream>
#include <map> #include <map>
@ -1887,7 +1946,7 @@ namespace Catch
ReporterConfig( std::ostream& _stream, ConfigData const& _fullConfig ) ReporterConfig( std::ostream& _stream, ConfigData const& _fullConfig )
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {} : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
std::ostream& stream() { return *m_stream; } std::ostream& stream() const { return *m_stream; }
std::string name() const { return m_fullConfig.name; } std::string name() const { return m_fullConfig.name; }
bool includeSuccessfulResults() const { return m_fullConfig.includeWhichResults == Include::SuccessfulResults; } bool includeSuccessfulResults() const { return m_fullConfig.includeWhichResults == Include::SuccessfulResults; }
bool warnAboutMissingAssertions() const { return m_fullConfig.warnings & ConfigData::WarnAbout::NoAssertions; } bool warnAboutMissingAssertions() const { return m_fullConfig.warnings & ConfigData::WarnAbout::NoAssertions; }
@ -1928,6 +1987,17 @@ namespace Catch
SourceLineInfo lineInfo; SourceLineInfo lineInfo;
}; };
struct ThreadedSectionInfo : SectionInfo, SharedImpl<> {
ThreadedSectionInfo( SectionInfo const& _sectionInfo, Ptr<ThreadedSectionInfo> const& _parent = Ptr<ThreadedSectionInfo>() )
: SectionInfo( _sectionInfo ),
parent( _parent )
{}
virtual ~ThreadedSectionInfo();
std::vector<Ptr<ThreadedSectionInfo> > children;
Ptr<ThreadedSectionInfo> parent;
};
struct AssertionStats : SharedImpl<> { struct AssertionStats : SharedImpl<> {
AssertionStats( AssertionResult const& _assertionResult, AssertionStats( AssertionResult const& _assertionResult,
Totals const& _totals ) Totals const& _totals )
@ -2012,6 +2082,10 @@ namespace Catch
// !Work In progress // !Work In progress
struct IStreamingReporter : IShared { struct IStreamingReporter : IShared {
virtual ~IStreamingReporter(); virtual ~IStreamingReporter();
// Implementing class must also provide the following static methid:
// static std::string getDescription();
virtual ReporterPreferences getPreferences() const = 0; virtual ReporterPreferences getPreferences() const = 0;
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
@ -2033,6 +2107,58 @@ namespace Catch
// - this would be used by the JUnit reporter, for example. // - this would be used by the JUnit reporter, for example.
// - it may be used by the basic reporter, too, but that would clear down the stack // - it may be used by the basic reporter, too, but that would clear down the stack
// as it goes // as it goes
struct AccumulatingReporter : SharedImpl<IStreamingReporter> {
AccumulatingReporter( ReporterConfig const& _config )
: stream( _config.stream() )
{}
virtual ~AccumulatingReporter();
virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
testRunInfo = _testRunInfo;
}
virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
unusedGroupInfo = _groupInfo;
}
virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
unusedTestCaseInfo = _testInfo;
}
virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
Ptr<ThreadedSectionInfo> sectionInfo = new ThreadedSectionInfo( _sectionInfo );
unusedSectionInfo = sectionInfo;
if( !currentSectionInfo ) {
currentSectionInfo = sectionInfo;
}
else {
currentSectionInfo->children.push_back( sectionInfo );
sectionInfo->parent = currentSectionInfo;
currentSectionInfo = sectionInfo;
}
}
virtual void sectionEnded( Ptr<SectionStats const> const& /* _sectionStats */ ) {
currentSectionInfo = currentSectionInfo->parent;
unusedSectionInfo = currentSectionInfo;
}
virtual void testCaseEnded( Ptr<TestCaseStats const> const& /* _testCaseStats */ ) {
unusedTestCaseInfo.reset();
}
virtual void testGroupEnded( Ptr<TestGroupStats const> const& /* _testGroupStats */ ) {
unusedGroupInfo.reset();
}
virtual void testRunEnded( Ptr<TestRunStats const> const& /* _testRunStats */ ) {
}
Option<TestRunInfo> testRunInfo;
Option<GroupInfo> unusedGroupInfo;
Option<TestCaseInfo> unusedTestCaseInfo;
Ptr<ThreadedSectionInfo> unusedSectionInfo;
Ptr<ThreadedSectionInfo> currentSectionInfo;
bool currentSectionOpen;
std::ostream& stream;
};
// Deprecated // Deprecated
struct IReporter : IShared { struct IReporter : IShared {
@ -2716,9 +2842,11 @@ namespace Matchers {
template<typename ExpressionT> template<typename ExpressionT>
struct Matcher : SharedImpl<IShared> struct Matcher : SharedImpl<IShared>
{ {
typedef ExpressionT ExpressionType;
virtual ~Matcher() {} virtual ~Matcher() {}
virtual Ptr<Matcher> clone() const = 0; virtual Ptr<Matcher> clone() const = 0;
virtual bool match( const ExpressionT& expr ) const = 0; virtual bool match( ExpressionT const& expr ) const = 0;
virtual std::string toString() const = 0; virtual std::string toString() const = 0;
}; };
@ -3008,7 +3136,7 @@ namespace Catch {
std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
getMutableRegistryHub().registerTest( TestCase( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) ); getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), "", name.c_str(), desc.c_str(), SourceLineInfo() ) );
noTestMethods++; noTestMethods++;
} }
} }
@ -3022,8 +3150,10 @@ namespace Catch {
namespace Impl { namespace Impl {
namespace NSStringMatchers { namespace NSStringMatchers {
struct StringHolder { template<typename MatcherT>
struct StringHolder : MatcherImpl<MatcherT, NSString*>{
StringHolder( NSString* substr ) : m_substr( [substr copy] ){} StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolder() { StringHolder() {
arcSafeRelease( m_substr ); arcSafeRelease( m_substr );
} }
@ -3031,54 +3161,50 @@ namespace Catch {
NSString* m_substr; NSString* m_substr;
}; };
struct Equals : StringHolder { struct Equals : StringHolder<Equals> {
Equals( NSString* substr ) : StringHolder( substr ){} Equals( NSString* substr ) : StringHolder( substr ){}
bool operator()( NSString* str ) const { virtual bool match( ExpressionType const& str ) const {
return [str isEqualToString:m_substr]; return [str isEqualToString:m_substr];
} }
friend std::ostream& operator<<( std::ostream& os, const Equals& matcher ) { virtual std::string toString() const {
os << "equals string: " << Catch::toString( matcher.m_substr ); return "equals string: \"" + Catch::toString( m_substr ) + "\"";
return os;
} }
}; };
struct Contains : StringHolder { struct Contains : StringHolder<Contains> {
Contains( NSString* substr ) : StringHolder( substr ){} Contains( NSString* substr ) : StringHolder( substr ){}
bool operator()( NSString* str ) const { virtual bool match( ExpressionType const& str ) const {
return [str rangeOfString:m_substr].location != NSNotFound; return [str rangeOfString:m_substr].location != NSNotFound;
} }
friend std::ostream& operator<<( std::ostream& os, const Contains& matcher ) { virtual std::string toString() const {
os << "contains: " << Catch::toString( matcher.m_substr ); return "contains string: \"" + Catch::toString( m_substr ) + "\"";
return os;
} }
}; };
struct StartsWith : StringHolder { struct StartsWith : StringHolder<StartsWith> {
StartsWith( NSString* substr ) : StringHolder( substr ){} StartsWith( NSString* substr ) : StringHolder( substr ){}
bool operator()( NSString* str ) const { virtual bool match( ExpressionType const& str ) const {
return [str rangeOfString:m_substr].location == 0; return [str rangeOfString:m_substr].location == 0;
} }
friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher ) { virtual std::string toString() const {
os << "starts with: " << Catch::toString( matcher.m_substr ); return "starts with: \"" + Catch::toString( m_substr ) + "\"";
return os;
} }
}; };
struct EndsWith : StringHolder { struct EndsWith : StringHolder<EndsWith> {
EndsWith( NSString* substr ) : StringHolder( substr ){} EndsWith( NSString* substr ) : StringHolder( substr ){}
bool operator()( NSString* str ) const { virtual bool match( ExpressionType const& str ) const {
return [str rangeOfString:m_substr].location == [str length] - [m_substr length]; return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
} }
friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher ) { virtual std::string toString() const {
os << "ends with: " << Catch::toString( matcher.m_substr ); return "ends with: \"" + Catch::toString( m_substr ) + "\"";
return os;
} }
}; };
@ -5498,8 +5624,8 @@ namespace Catch {
className( _className ), className( _className ),
description( _description ), description( _description ),
tags( _tags ), tags( _tags ),
isHidden( _isHidden ), lineInfo( _lineInfo ),
lineInfo( _lineInfo ) isHidden( _isHidden )
{} {}
TestCaseInfo::TestCaseInfo( const TestCaseInfo& other ) TestCaseInfo::TestCaseInfo( const TestCaseInfo& other )
@ -5507,8 +5633,8 @@ namespace Catch {
className( other.className ), className( other.className ),
description( other.description ), description( other.description ),
tags( other.tags ), tags( other.tags ),
isHidden( other.isHidden ), lineInfo( other.lineInfo ),
lineInfo( other.lineInfo ) isHidden( other.isHidden )
{} {}
TestCase::TestCase( ITestCase* testCase, const TestCaseInfo& info ) : TestCaseInfo( info ), test( testCase ) {} TestCase::TestCase( ITestCase* testCase, const TestCaseInfo& info ) : TestCaseInfo( info ), test( testCase ) {}
@ -5580,7 +5706,7 @@ namespace Catch {
namespace Catch { namespace Catch {
// These numbers are maintained by a script // These numbers are maintained by a script
Version libraryVersion( 0, 9, 8, "integration" ); Version libraryVersion( 0, 9, 9, "integration" );
} }
// #included from: ../reporters/catch_reporter_basic.hpp // #included from: ../reporters/catch_reporter_basic.hpp
@ -6557,6 +6683,132 @@ namespace Catch {
} // end namespace Catch } // end namespace Catch
// #included from: ../reporters/catch_reporter_console.hpp
#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
namespace Catch {
struct ConsoleReporter : AccumulatingReporter {
ConsoleReporter( ReporterConfig const& _config )
: AccumulatingReporter( _config )
{}
virtual ~ConsoleReporter();
static std::string getDescription() {
return "Reports test results as plain lines of text";
}
virtual ReporterPreferences getPreferences() const {
ReporterPreferences prefs;
prefs.shouldRedirectStdOut = false;
return prefs;
}
void lazyPrintRunInfo() {
stream << "[Started testing: " << testRunInfo->name << "]" << std::endl;
testRunInfo.reset();
}
void lazyPrintGroupInfo() {
if( !unusedGroupInfo->name.empty() )
stream << "[Group: '" << unusedGroupInfo->name << "']" << std::endl;
unusedGroupInfo.reset();
}
void lazyPrintTestCaseInfo() {
stream << "[Test case: '" << unusedTestCaseInfo->name << "']" << std::endl;
unusedTestCaseInfo.reset();
}
std::string makeSectionPath( ThreadedSectionInfo const * section, std::string const& delimiter ) {
std::string sectionPath = "'" + section->name + "'";
while( ( section = section->parent.get() ) )
sectionPath = "'" + section->name + "'" + delimiter + sectionPath;
return sectionPath;
}
void lazyPrintSectionInfo() {
ThreadedSectionInfo* section = unusedSectionInfo.get();
std::string sectionPath = makeSectionPath( section, ", " );
if( sectionPath.size() > 60 )
sectionPath = makeSectionPath( section, ",\n " );
stream << "[Section: " << sectionPath << "]" << std::endl;
unusedSectionInfo.reset();
}
void lazyPrint() {
if( testRunInfo )
lazyPrintRunInfo();
if( unusedGroupInfo )
lazyPrintGroupInfo();
if( unusedTestCaseInfo )
lazyPrintTestCaseInfo();
if( unusedSectionInfo )
lazyPrintSectionInfo();
}
virtual void assertionStarting( AssertionInfo const& _assertionInfo ) {
}
virtual void assertionEnded( Ptr<AssertionStats const> const& _assertionStats ) {
if( !_assertionStats->assertionResult.isOk() )
lazyPrint();
}
void printAssertionCounts( std::string const& label, Counts const& counts, std::string const& allPrefix = "All " ) {
if( counts.passed )
stream << counts.failed << " of " << counts.total() << " " << label << "s failed";
else
stream << ( counts.failed > 1 ? allPrefix : "" ) << pluralise( counts.failed, label ) << " failed";
}
void printTotals( const Totals& totals, const std::string& allPrefix = "All " ) {
if( totals.assertions.total() == 0 ) {
stream << "No tests ran";
}
else if( totals.assertions.failed ) {
TextColour colour( TextColour::ResultError );
printAssertionCounts( "test case", totals.testCases, allPrefix );
if( totals.testCases.failed > 0 ) {
stream << " (";
printAssertionCounts( "assertion", totals.assertions, allPrefix );
stream << ")";
}
}
else {
TextColour colour( TextColour::ResultSuccess );
stream << allPrefix << "tests passed ("
<< pluralise( totals.assertions.passed, "assertion" ) << " in "
<< pluralise( totals.testCases.passed, "test case" ) << ")";
}
}
virtual void sectionEnded( Ptr<SectionStats const> const& _sectionStats ) {
if( !unusedSectionInfo ) {
stream << "[Summary for section '" << _sectionStats->sectionInfo.name << "': ";
printAssertionCounts( "assertion", _sectionStats->assertions );
stream << "]\n" << std::endl;
}
AccumulatingReporter::sectionEnded( _sectionStats );
}
virtual void testCaseEnded( Ptr<TestCaseStats const> const& _testCaseStats ) {
if( !unusedTestCaseInfo ) {
stream << "[Summary for test case '" << _testCaseStats->testInfo.name << "': ";
printTotals( _testCaseStats->totals );
stream << "]\n" << std::endl;
}
AccumulatingReporter::testCaseEnded( _testCaseStats );
}
virtual void testGroupEnded( Ptr<TestGroupStats const> const& _testGroupStats ) {
// !TBD
AccumulatingReporter::testGroupEnded( _testGroupStats );
}
virtual void testRunEnded( Ptr<TestRunStats const> const& _testRunStats ) {
// !TBD
AccumulatingReporter::testRunEnded( _testRunStats );
}
};
INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
} // end namespace Catch
namespace Catch { namespace Catch {
NonCopyable::~NonCopyable() {} NonCopyable::~NonCopyable() {}
IShared::~IShared() {} IShared::~IShared() {}
@ -6579,8 +6831,11 @@ namespace Catch {
TestCaseStats::~TestCaseStats() {} TestCaseStats::~TestCaseStats() {}
TestGroupStats::~TestGroupStats() {} TestGroupStats::~TestGroupStats() {}
TestRunStats::~TestRunStats() {} TestRunStats::~TestRunStats() {}
ThreadedSectionInfo::~ThreadedSectionInfo() {}
BasicReporter::~BasicReporter() {} BasicReporter::~BasicReporter() {}
AccumulatingReporter::~AccumulatingReporter() {}
ConsoleReporter::~ConsoleReporter() {}
IRunner::~IRunner() {} IRunner::~IRunner() {}
IMutableContext::~IMutableContext() {} IMutableContext::~IMutableContext() {}
IConfig::~IConfig() {} IConfig::~IConfig() {}