2 #ifndef TUT_CPPUNIT_REPORTER
\r
3 #define TUT_CPPUNIT_REPORTER
\r
5 #include <tut/tut.hpp>
\r
16 * CppUnit TUT reporter
\r
18 class cppunit_reporter : public tut::callback
\r
20 std::vector<tut::test_result> failed_tests_;
\r
21 std::vector<tut::test_result> passed_tests_;
\r
22 const std::string filename_;
\r
23 std::auto_ptr<std::ostream> stream_;
\r
26 cppunit_reporter(const cppunit_reporter &);
\r
27 cppunit_reporter &operator=(const cppunit_reporter &);
\r
30 explicit cppunit_reporter(const std::string &filename = "testResult.xml")
\r
33 filename_(filename),
\r
34 stream_(new std::ofstream(filename_.c_str()))
\r
36 if (!stream_->good()) {
\r
37 throw tut_error("Cannot open output file `" + filename_ + "`");
\r
41 explicit cppunit_reporter(std::ostream &stream)
\r
51 if(filename_.empty())
\r
59 failed_tests_.clear();
\r
60 passed_tests_.clear();
\r
63 void test_completed(const tut::test_result& tr)
\r
65 assert(tr.result != test_result::dummy );
\r
66 if ( (tr.result == test_result::ok) ||
\r
67 (tr.result == test_result::skipped) )
\r
69 passed_tests_.push_back(tr);
\r
73 failed_tests_.push_back(tr);
\r
77 void run_completed()
\r
81 std::string failure_type;
\r
82 std::string failure_msg;
\r
84 *stream_ << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" << std::endl
\r
85 << "<TestRun>" << std::endl;
\r
87 if (failed_tests_.size() > 0)
\r
89 *stream_ << " <FailedTests>" << std::endl;
\r
91 for (unsigned int i=0; i<failed_tests_.size(); i++)
\r
93 switch (failed_tests_[i].result)
\r
95 case test_result::fail:
\r
96 failure_type = "Assertion";
\r
100 case test_result::ex:
\r
101 failure_type = "Assertion";
\r
102 failure_msg = "Thrown exception: " + failed_tests_[i].exception_typeid + '\n';
\r
105 case test_result::warn:
\r
106 failure_type = "Assertion";
\r
107 failure_msg = "Destructor failed\n";
\r
110 case test_result::term:
\r
111 failure_type = "Error";
\r
112 failure_msg = "Test application terminated abnormally\n";
\r
115 case test_result::ex_ctor:
\r
116 failure_type = "Error";
\r
117 failure_msg = "Constructor has thrown an exception: " + failed_tests_[i].exception_typeid + '\n';
\r
120 case test_result::rethrown:
\r
121 failure_type = "Assertion";
\r
122 failure_msg = "Child failed\n";
\r
125 default: // ok, skipped, dummy
\r
126 failure_type = "Error";
\r
127 failure_msg = "Unknown test status, this should have never happened. "
\r
128 "You may just have found a bug in TUT, please report it immediately.\n";
\r
133 *stream_ << " <FailedTest id=\"" << failed_tests_[i].test << "\">" << std::endl
\r
134 << " <Name>" << encode(failed_tests_[i].group) + "::" + encode(failed_tests_[i].name) << "</Name>" << std::endl
\r
135 << " <FailureType>" << failure_type << "</FailureType>" << std::endl
\r
136 << " <Location>" << std::endl
\r
137 << " <File>Unknown</File>" << std::endl
\r
138 << " <Line>Unknown</Line>" << std::endl
\r
139 << " </Location>" << std::endl
\r
140 << " <Message>" << encode(failure_msg + failed_tests_[i].message) << "</Message>" << std::endl
\r
141 << " </FailedTest>" << std::endl;
\r
144 *stream_ << " </FailedTests>" << std::endl;
\r
147 /* *********************** passed tests ***************************** */
\r
148 if (passed_tests_.size() > 0) {
\r
149 *stream_ << " <SuccessfulTests>" << std::endl;
\r
151 for (unsigned int i=0; i<passed_tests_.size(); i++)
\r
153 *stream_ << " <Test id=\"" << passed_tests_[i].test << "\">" << std::endl
\r
154 << " <Name>" << encode(passed_tests_[i].group) + "::" + encode(passed_tests_[i].name) << "</Name>" << std::endl
\r
155 << " </Test>" << std::endl;
\r
158 *stream_ << " </SuccessfulTests>" << std::endl;
\r
161 /* *********************** statistics ***************************** */
\r
162 *stream_ << " <Statistics>" << std::endl
\r
163 << " <Tests>" << (failed_tests_.size() + passed_tests_.size()) << "</Tests>" << std::endl
\r
164 << " <FailuresTotal>" << failed_tests_.size() << "</FailuresTotal>" << std::endl
\r
165 << " <Errors>" << errors << "</Errors>" << std::endl
\r
166 << " <Failures>" << failures << "</Failures>" << std::endl
\r
167 << " </Statistics>" << std::endl;
\r
169 /* *********************** footer ***************************** */
\r
170 *stream_ << "</TestRun>" << std::endl;
\r
173 virtual bool all_ok() const
\r
175 return failed_tests_.empty();
\r
179 * \brief Encodes text to XML
\r
180 * XML-reserved characters (e.g. "<") are encoded according to specification
\r
181 * @param text text to be encoded
\r
182 * @return encoded string
\r
184 static std::string encode(const std::string & text)
\r
188 for (unsigned int i=0; i<text.length(); ++i) {
\r