tut logo

tut_xml_reporter.hpp Source File


tut_xml_reporter.hpp
1 #ifndef TUT_XML_REPORTER
2 #define TUT_XML_REPORTER
3 #include <tut/tut_config.hpp>
4 #include <tut/tut.hpp>
5 #include <tut/tut_cppunit_reporter.hpp>
6 #include <cassert>
7 #include <string>
8 #include <fstream>
9 #include <vector>
10 #include <stdexcept>
11 
12 namespace tut
13 {
14 
21 {
22  typedef std::vector<tut::test_result> TestResults;
23  typedef std::map<std::string, TestResults> TestGroups;
24 
25  TestGroups all_tests_;
26  const std::string filename_;
27  std::auto_ptr<std::ostream> stream_;
28 
37  std::string xml_build_testcase(const tut::test_result & tr, const std::string & failure_type,
38  const std::string & failure_msg, int pid = 0)
39  {
40  using std::endl;
41  using std::string;
42 
43  std::ostringstream out;
44 
45  if ( (tr.result == test_result::ok) ||
46  (tr.result == test_result::skipped) )
47  {
48  out << " <testcase classname=\"" << cppunit_reporter::encode(tr.group) << "\" name=\"" << cppunit_reporter::encode(tr.name) << "\"/>";
49  }
50  else
51  {
52  string err_msg = cppunit_reporter::encode(failure_msg + tr.message);
53 
54  string tag; // determines tag name: "failure" or "error"
55  if ( tr.result == test_result::fail || tr.result == test_result::warn ||
56  tr.result == test_result::ex || tr.result == test_result::ex_ctor || tr.result == test_result::rethrown )
57  {
58  tag = "failure";
59  }
60  else
61  {
62  tag = "error";
63  }
64 
65  out << " <testcase classname=\"" << cppunit_reporter::encode(tr.group) << "\" name=\"" << cppunit_reporter::encode(tr.name) << "\">" << endl;
66  out << " <" << tag << " message=\"" << err_msg << "\"" << " type=\"" << failure_type << "\"";
67 #if defined(TUT_USE_POSIX)
68  if(pid != getpid())
69  {
70  out << " child=\"" << pid << "\"";
71  }
72 #else
73  (void)pid;
74 #endif
75  out << ">" << err_msg << "</" << tag << ">" << endl;
76  out << " </testcase>";
77  }
78 
79  return out.str();
80  }
81 
92  std::string xml_build_testsuite(int errors, int failures, int total,
93  const std::string & name, const std::string & testcases)
94  {
95  std::ostringstream out;
96 
97  out << " <testsuite errors=\"" << errors << "\" failures=\"" << failures << "\" tests=\"" << total << "\" name=\"" << cppunit_reporter::encode(name) << "\">" << std::endl;
98  out << testcases;
99  out << " </testsuite>";
100 
101  return out.str();
102  }
103 
104 public:
105  int ok_count;
110 
115  xml_reporter(const std::string & filename)
116  : all_tests_(),
117  filename_(filename),
118  stream_(new std::ofstream(filename_.c_str())),
119  ok_count(0),
120  exceptions_count(0),
121  failures_count(0),
123  warnings_count(0)
124  {
125  if (!stream_->good()) {
126  throw tut_error("Cannot open output file `" + filename_ + "`");
127  }
128  }
129 
130  xml_reporter(std::ostream & stream)
131  : all_tests_(),
132  filename_(),
133  stream_(&stream),
134  ok_count(0),
135  exceptions_count(0),
136  failures_count(0),
138  warnings_count(0)
139  {
140  }
141 
142  ~xml_reporter()
143  {
144  if(filename_.empty())
145  {
146  stream_.release();
147  }
148  }
149 
154  virtual void run_started()
155  {
156  ok_count = 0;
157  exceptions_count = 0;
158  failures_count = 0;
159  terminations_count = 0;
160  warnings_count = 0;
161  all_tests_.clear();
162  }
163 
168  virtual void test_completed(const tut::test_result& tr)
169  {
170  // update global statistics
171  switch (tr.result) {
172  case test_result::ok:
173  case test_result::skipped:
174  ok_count++;
175  break;
176  case test_result::fail:
177  case test_result::rethrown:
178  failures_count++;
179  break;
180  case test_result::ex:
181  case test_result::ex_ctor:
183  break;
184  case test_result::warn:
185  warnings_count++;
186  break;
187  case test_result::term:
189  break;
190  case tut::test_result::dummy:
191  assert(!"Should never be called");
192  } // switch
193 
194  // add test result to results table
195  all_tests_[tr.group].push_back(tr);
196  }
197 
203  virtual void run_completed()
204  {
205  /* *********************** header ***************************** */
206  *stream_ << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" << std::endl;
207  *stream_ << "<testsuites>" << std::endl;
208 
209  // iterate over all test groups
210  for (TestGroups::const_iterator tgi = all_tests_.begin(); tgi != all_tests_.end(); ++tgi)
211  {
212  /* per-group statistics */
213  int passed = 0; // passed in single group
214  int exceptions = 0; // exceptions in single group
215  int failures = 0; // failures in single group
216  int terminations = 0; // terminations in single group
217  int warnings = 0; // warnings in single group
218  int errors = 0; // errors in single group
219 
220 
221  // output is written to string stream buffer, because JUnit format <testsuite> tag
222  // contains statistics, which aren't known yet
223  std::ostringstream out;
224 
225  // iterate over all test cases in the current test group
226  const TestResults &results = tgi->second;
227  for (TestResults::const_iterator tri = results.begin(); tri != results.end(); ++tri)
228  {
229  std::string failure_type; // string describing the failure type
230  std::string failure_msg; // a string with failure message
231 
232  switch (tri->result)
233  {
234  case test_result::ok:
235  case test_result::skipped:
236  passed++;
237  break;
238  case test_result::fail:
239  failure_type = "Assertion";
240  failure_msg = "";
241  failures++;
242  break;
243  case test_result::ex:
244  failure_type = "Assertion";
245  failure_msg = "Thrown exception: " + tri->exception_typeid + '\n';
246  exceptions++;
247  break;
248  case test_result::warn:
249  failure_type = "Assertion";
250  failure_msg = "Destructor failed.\n";
251  warnings++;
252  break;
253  case test_result::term:
254  failure_type = "Error";
255  failure_msg = "Test application terminated abnormally.\n";
256  terminations++;
257  break;
258  case test_result::ex_ctor:
259  failure_type = "Assertion";
260  failure_msg = "Constructor has thrown an exception: " + tri->exception_typeid + ".\n";
261  exceptions++;
262  break;
263  case test_result::rethrown:
264  failure_type = "Assertion";
265  failure_msg = "Child failed.\n";
266  failures++;
267  break;
268  default:
269  failure_type = "Error";
270  failure_msg = "Unknown test status, this should have never happened. "
271  "You may just have found a bug in TUT, please report it immediately.\n";
272  errors++;
273  break;
274  } // switch
275 
276 #if defined(TUT_USE_POSIX)
277  out << xml_build_testcase(*tri, failure_type, failure_msg, tri->pid) << std::endl;
278 #else
279  out << xml_build_testcase(*tri, failure_type, failure_msg) << std::endl;
280 #endif
281  } // iterate over all test cases
282 
283  // calculate per-group statistics
284  int stat_errors = terminations + errors;
285  int stat_failures = failures + warnings + exceptions;
286  int stat_all = stat_errors + stat_failures + passed;
287 
288  *stream_ << xml_build_testsuite(stat_errors, stat_failures, stat_all, (*tgi).first/* name */, out.str()/* testcases */) << std::endl;
289  } // iterate over all test groups
290 
291  *stream_ << "</testsuites>" << std::endl;
292  }
293 
297  virtual bool all_ok() const
298  {
300  };
301 };
302 
303 }
304 
305 #endif
Definition: tut_exception.hpp:13
std::string group
Definition: tut_result.hpp:74
int warnings_count
number of tests that would terminate
Definition: tut_xml_reporter.hpp:109
int terminations_count
number of tests that failed
Definition: tut_xml_reporter.hpp:108
test finished successfully
Definition: tut_result.hpp:91
std::string name
Definition: tut_result.hpp:84
virtual bool all_ok() const
Returns true, if all tests passed.
Definition: tut_xml_reporter.hpp:297
JUnit XML TUT reporter.
Definition: tut_xml_reporter.hpp:20
test finished successfully, but test destructor throwed
Definition: tut_result.hpp:94
virtual void test_completed(const tut::test_result &tr)
Callback function This function is called when test completes. Counters are updated here...
Definition: tut_xml_reporter.hpp:168
virtual void run_completed()
Callback function This function is called when all tests are completed. It generates XML output to fi...
Definition: tut_xml_reporter.hpp:203
int failures_count
number of tests that threw exceptions
Definition: tut_xml_reporter.hpp:107
test failed with ensure() or fail() methods
Definition: tut_result.hpp:92
xml_reporter(const std::string &filename)
number of tests where destructors threw an exception
Definition: tut_xml_reporter.hpp:115
std::string message
Definition: tut_result.hpp:107
Definition: tut_result.hpp:69
test forced test application to terminate abnormally
Definition: tut_result.hpp:95
test throwed an exceptions
Definition: tut_result.hpp:93
static std::string encode(const std::string &text)
Encodes text to XML XML-reserved characters (e.g. &quot;&lt;&quot;) are encoded according to specification.
Definition: tut_cppunit_reporter.hpp:184
int exceptions_count
number of passed tests
Definition: tut_xml_reporter.hpp:106
Definition: tut_runner.hpp:38
virtual void run_started()
Callback function This function is called before the first test is executed. It initializes counters...
Definition: tut_xml_reporter.hpp:154

All Rights Reserved. Generated on Wed Dec 18 2013 11:19:52 for TUT by doxygen 1.8.5