Go to the documentation of this file.00001 #ifndef __HAYAI_JUNITXMLOUTPUTTER
00002 #define __HAYAI_JUNITXMLOUTPUTTER
00003 #include <iomanip>
00004 #include <ostream>
00005 #include <vector>
00006 #include <sstream>
00007 #include <map>
00008
00009 #include "hayai/hayai_outputter.hpp"
00010
00011
00012 namespace hayai
00013 {
00015 class JUnitXmlOutputter
00016 : public Outputter
00017 {
00018 private:
00020 class TestCase
00021 {
00022 public:
00023 TestCase(const std::string& fixtureName,
00024 const std::string& testName,
00025 const TestParametersDescriptor& parameters,
00026 const TestResult* result)
00027 {
00028
00029 std::stringstream nameStream;
00030 WriteTestNameToStream(nameStream,
00031 fixtureName,
00032 testName,
00033 parameters);
00034 Name = nameStream.str();
00035
00036
00037 Skipped = !result;
00038
00039 if (result)
00040 {
00041 std::stringstream timeStream;
00042 timeStream << std::fixed
00043 << std::setprecision(9)
00044 << (result->IterationTimeAverage() / 1e9);
00045 Time = timeStream.str();
00046 }
00047 }
00048
00049
00050 std::string Name;
00051 std::string Time;
00052 bool Skipped;
00053 };
00054
00055
00057 typedef std::map<std::string, std::vector<TestCase> > TestSuiteMap;
00058 public:
00060
00063 JUnitXmlOutputter(std::ostream& stream)
00064 : _stream(stream)
00065 {
00066
00067 }
00068
00069
00070 virtual void Begin(const std::size_t& enabledCount,
00071 const std::size_t& disabledCount)
00072 {
00073 (void)enabledCount;
00074 (void)disabledCount;
00075 }
00076
00077
00078 virtual void End(const std::size_t& executedCount,
00079 const std::size_t& disabledCount)
00080 {
00081 (void)executedCount;
00082 (void)disabledCount;
00083
00084
00085 _stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
00086 << std::endl
00087 << "<testsuites>" << std::endl;
00088
00089
00090 for (TestSuiteMap::iterator testSuiteIt = _testSuites.begin();
00091 testSuiteIt != _testSuites.end();
00092 ++testSuiteIt)
00093 {
00094 _stream << " <testsuite name=\"" << testSuiteIt->first
00095 << "\" tests=\"" << testSuiteIt->second.size() << "\">"
00096 << std::endl;
00097
00098
00099 for (std::vector<TestCase>::iterator testCaseIt =
00100 testSuiteIt->second.begin();
00101 testCaseIt != testSuiteIt->second.end();
00102 ++testCaseIt)
00103 {
00104 _stream << " <testcase name=\"";
00105 WriteEscapedString(testCaseIt->Name);
00106 _stream << "\"";
00107
00108 if (!testCaseIt->Skipped)
00109 _stream << " time=\"" << testCaseIt->Time << "\" />"
00110 << std::endl;
00111 else
00112 {
00113 _stream << ">" << std::endl
00114 << " <skipped />" << std::endl
00115 << " </testcase>" << std::endl;
00116 }
00117 }
00118
00119 _stream << " </testsuite>" << std::endl;
00120 }
00121
00122 _stream << "</testsuites>" << std::endl;
00123 }
00124
00125
00126 virtual void BeginTest(const std::string& fixtureName,
00127 const std::string& testName,
00128 const TestParametersDescriptor& parameters,
00129 const std::size_t& runsCount,
00130 const std::size_t& iterationsCount)
00131 {
00132 (void)fixtureName;
00133 (void)testName;
00134 (void)parameters;
00135 (void)runsCount;
00136 (void)iterationsCount;
00137 }
00138
00139
00140 virtual void SkipDisabledTest(const std::string& fixtureName,
00141 const std::string& testName,
00142 const TestParametersDescriptor& parameters,
00143 const std::size_t& runsCount,
00144 const std::size_t& iterationsCount)
00145 {
00146 (void)fixtureName;
00147 (void)testName;
00148 (void)parameters;
00149 (void)runsCount;
00150 (void)iterationsCount;
00151 }
00152
00153
00154 virtual void EndTest(const std::string& fixtureName,
00155 const std::string& testName,
00156 const TestParametersDescriptor& parameters,
00157 const TestResult& result)
00158 {
00159 (void)fixtureName;
00160 (void)testName;
00161 (void)parameters;
00162
00163 TestSuiteMap::iterator fixtureIt =
00164 _testSuites.find(fixtureName);
00165
00166 if (fixtureIt == _testSuites.end())
00167 {
00168 _testSuites[fixtureName] = std::vector<TestCase>();
00169 fixtureIt = _testSuites.find(fixtureName);
00170 }
00171
00172 std::vector<TestCase>& testCases = fixtureIt->second;
00173
00174 testCases.push_back(TestCase(fixtureName,
00175 testName,
00176 parameters,
00177 &result));
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 }
00212 private:
00214
00219 void WriteEscapedString(const std::string& str)
00220 {
00221 std::string::const_iterator it = str.begin();
00222
00223 while (it != str.end())
00224 {
00225 char c = *it++;
00226
00227 switch (c)
00228 {
00229 case '"':
00230 _stream << """;
00231 break;
00232
00233 case '\'':
00234 _stream << "'";
00235 break;
00236
00237 case '<':
00238 _stream << "<";
00239 break;
00240
00241 case '>':
00242 _stream << ">";
00243 break;
00244
00245 case '&':
00246 _stream << "&";
00247 break;
00248
00249 default:
00250 _stream << c;
00251 break;
00252 }
00253 }
00254 }
00255
00256
00257 std::ostream& _stream;
00258 TestSuiteMap _testSuites;
00259 };
00260 }
00261
00262 #endif