First commit of (in progress) TeamCity reporter
Should run but is not complete
diff --git a/include/catch.hpp b/include/catch.hpp
index 4251cd0..9f82c72 100644
--- a/include/catch.hpp
+++ b/include/catch.hpp
@@ -11,11 +11,11 @@
#include "internal/catch_suppress_warnings.h"
-#ifdef CATCH_CONFIG_MAIN
-# define CATCH_CONFIG_RUNNER
+#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
+# define CATCH_IMPL
#endif
-#ifdef CATCH_CONFIG_RUNNER
+#ifdef CATCH_IMPL
# ifndef CLARA_CONFIG_MAIN
# define CLARA_CONFIG_MAIN_NOT_DEFINED
# define CLARA_CONFIG_MAIN
@@ -43,7 +43,7 @@
#include "internal/catch_objc.hpp"
#endif
-#ifdef CATCH_CONFIG_RUNNER
+#ifdef CATCH_IMPL
#include "internal/catch_impl.hpp"
#endif
diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h
index 872b65c..6e058bf 100644
--- a/include/internal/catch_interfaces_reporter.h
+++ b/include/internal/catch_interfaces_reporter.h
@@ -238,6 +238,7 @@
virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
+ // The return value indicates if the messages buffer should be cleared:
virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp
index 34ffbc2..1c510ef 100644
--- a/include/internal/catch_list.hpp
+++ b/include/internal/catch_list.hpp
@@ -139,7 +139,7 @@
}
inline std::size_t listReporters( Config const& /*config*/ ) {
- Catch::cout() << "Available reports:\n";
+ Catch::cout() << "Available reporters:\n";
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
std::size_t maxNameLen = 0;
diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp
new file mode 100644
index 0000000..127ad7b
--- /dev/null
+++ b/include/reporters/catch_reporter_teamcity.hpp
@@ -0,0 +1,124 @@
+/*
+ * Created by Phil Nash on 19th December 2014
+ * Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * 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_TEAMCITY_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
+
+#include "catch_reporter_bases.hpp"
+
+#include "../internal/catch_reporter_registrars.hpp"
+
+#include <cstring>
+
+namespace Catch {
+
+ struct TeamCityReporter : StreamingReporterBase {
+ TeamCityReporter( ReporterConfig const& _config )
+ : StreamingReporterBase( _config )
+ {}
+
+ static bool replace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
+ std::size_t i = str.find( replaceThis );
+ if( i != std::string::npos ) {
+ str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
+ return true;
+ }
+ return false;
+ }
+ static std::string escape( std::string const& str ) {
+ std::string escaped = str;
+ while( replace( escaped, "\'", "|\'" ) ||
+ replace( escaped, "\n", "|n" ) ||
+ replace( escaped, "\r", "|r" ) ||
+ replace( escaped, "|", "||" ) ||
+ replace( escaped, "[", "|[" ) ||
+ replace( escaped, "]", "|]" ) );
+ return escaped;
+ }
+ virtual ~TeamCityReporter();
+
+ static std::string getDescription() {
+ return "Reports test results as TeamCity service messages";
+ }
+ virtual ReporterPreferences getPreferences() const {
+ ReporterPreferences prefs;
+ prefs.shouldRedirectStdOut = true;
+ return prefs;
+ }
+
+ // !TBD: ignored tests
+
+ virtual void noMatchingTestCases( std::string const& /* spec */ ) {}
+
+ virtual void testGroupStarting( GroupInfo const& groupInfo ) {
+ StreamingReporterBase::testGroupStarting( groupInfo );
+ stream << "##teamcity[testSuiteStarted name='"
+ << escape( groupInfo.name ) << "']\n";
+ }
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
+ StreamingReporterBase::testGroupEnded( testGroupStats );
+ stream << "##teamcity[testSuiteFinished name='"
+ << escape( testGroupStats.groupInfo.name ) << "']\n";
+ }
+
+
+ virtual void assertionStarting( AssertionInfo const& ) {
+ }
+
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) {
+ if( !assertionStats.assertionResult.isOk() ) {
+ stream << "##teamcity[testFailed"
+ << " name='" << escape( currentTestCaseInfo->name )<< "'"
+ << " message='message here'" // !TBD
+ << " details='details?'" // !TBD
+ << "]\n";
+ }
+ return true;
+ }
+
+// virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
+// // !TBD
+// }
+// virtual void sectionEnded( SectionStats const& _sectionStats ) {
+// // !TBD
+// }
+
+ virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
+ StreamingReporterBase::testCaseStarting( testInfo );
+ stream << "##teamcity[testStarted name='"
+ << escape( testInfo.name ) << "']\n";
+ }
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
+ StreamingReporterBase::testCaseEnded( testCaseStats );
+ if( !testCaseStats.stdOut.empty() )
+ stream << "##teamcity[testStdOut name='"
+ << escape( testCaseStats.testInfo.name )
+ << "' out='" << escape( testCaseStats.stdOut ) << "']\n";
+ if( !testCaseStats.stdErr.empty() )
+ stream << "##teamcity[testStdErr name='"
+ << escape( testCaseStats.testInfo.name )
+ << "' out='" << escape( testCaseStats.stdErr ) << "']\n";
+ stream << "##teamcity[testFinished name='"
+ << escape( testCaseStats.testInfo.name ) << "']\n";
+ }
+// virtual void testRunEnded( TestRunStats const& _testRunStats ) {
+// // !TBD
+// }
+
+ private:
+
+ };
+
+#ifdef CATCH_IMPL
+ TeamCityReporter::~TeamCityReporter() {}
+#endif
+
+ INTERNAL_CATCH_REGISTER_REPORTER( "teamcity", TeamCityReporter )
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp
index b6fc869..6917678 100644
--- a/projects/SelfTest/TestMain.cpp
+++ b/projects/SelfTest/TestMain.cpp
@@ -8,6 +8,7 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
+#include "reporters/catch_reporter_teamcity.hpp"
// Some example tag aliases
CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" )
diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj
index 70f402e..e4b59f5 100644
--- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj
+++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj
@@ -96,6 +96,7 @@
26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = "<group>"; };
26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = "<group>"; };
268F47B018A93F7800D8C14F /* catch_clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_clara.h; sourceTree = "<group>"; };
+ 2691574A1A4480C50054F1ED /* catch_reporter_teamcity.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_teamcity.hpp; sourceTree = "<group>"; };
26926E8318D7777D004E10F2 /* clara.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/external/clara.h; sourceTree = "<group>"; };
26926E8418D77809004E10F2 /* tbc_text_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tbc_text_format.h; path = ../../../../include/external/tbc_text_format.h; sourceTree = "<group>"; };
26948284179A9AB900ED166E /* SectionTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionTrackerTests.cpp; path = ../../../SelfTest/SectionTrackerTests.cpp; sourceTree = "<group>"; };
@@ -313,6 +314,7 @@
4A6D0C67149B3E3D00DB3EAA /* catch_reporter_junit.hpp */,
4A6D0C68149B3E3D00DB3EAA /* catch_reporter_xml.hpp */,
4AB42F84166F3E1A0099F2C8 /* catch_reporter_console.hpp */,
+ 2691574A1A4480C50054F1ED /* catch_reporter_teamcity.hpp */,
);
name = reporters;
path = ../../../../include/reporters;