113 std::ostringstream oss;
119 ComputeSummaryCounters(summary, &total, &passed, &failed, &errors, &skipped);
122 if (timestamp == absl::InfinitePast()) {
123 timestamp = absl::Now();
131 << absl::FormatTime(
"%Y-%m-%d %H:%M:%S", timestamp, absl::UTCTimeZone())
133 oss <<
"Totals: " << total <<
" (" << passed <<
" passed, " << failed
134 <<
" failed, " << errors <<
" errors, " << skipped <<
" skipped)";
136 absl::Duration duration = TotalDuration(summary);
137 if (duration > absl::ZeroDuration()) {
139 << absl::StrFormat(
"%.2fs", absl::ToDoubleSeconds(duration));
143 for (
const auto& result : summary.
results) {
144 std::string group_name;
146 group_name = result.group->name;
147 }
else if (result.test) {
148 group_name = result.test->group_name;
150 std::string test_name = result.test ? result.test->name :
"<unnamed>";
151 oss <<
" [" << OutcomeToString(result.outcome) <<
"] ";
152 if (!group_name.empty()) {
153 oss << group_name <<
" :: ";
156 if (result.duration > absl::ZeroDuration()) {
157 oss <<
" (" << absl::StrFormat(
"%.2fs",
158 absl::ToDoubleSeconds(result.duration))
162 if (!result.message.empty() &&
164 oss <<
" " << result.message <<
"\n";
166 if (!result.assertions.empty() &&
168 for (
const auto& assertion : result.assertions) {
169 oss <<
" - " << assertion.description <<
" : "
170 << (assertion.passed ?
"PASS" :
"FAIL");
171 if (!assertion.error_message.empty()) {
172 oss <<
" (" << assertion.error_message <<
")";
184 std::ostringstream oss;
190 ComputeSummaryCounters(summary, &total, &passed, &failed, &errors, &skipped);
193 if (timestamp == absl::InfinitePast()) {
194 timestamp = absl::Now();
196 absl::Duration duration = TotalDuration(summary);
198 std::string suite_name =
201 oss <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
202 oss <<
"<testsuite name=\"" << EscapeXml(suite_name) <<
"\" tests=\""
203 << total <<
"\" failures=\"" << failed <<
"\" errors=\"" << errors
204 <<
"\" skipped=\"" << skipped <<
"\" time=\""
205 << absl::StrFormat(
"%.3f", absl::ToDoubleSeconds(duration))
208 absl::FormatTime(
"%Y-%m-%dT%H:%M:%SZ", timestamp,
209 absl::UTCTimeZone()))
212 for (
const auto& result : summary.
results) {
213 std::string classname;
215 classname = result.group->name;
216 }
else if (result.test) {
217 classname = result.test->group_name;
219 std::string test_name = result.test ? result.test->name :
"Test";
220 oss <<
" <testcase classname=\"" << EscapeXml(classname)
221 <<
"\" name=\"" << EscapeXml(test_name) <<
"\" time=\""
222 << absl::StrFormat(
"%.3f", absl::ToDoubleSeconds(result.duration))
226 std::string body = result.message;
227 if (!result.assertions.empty()) {
228 std::vector<std::string> assertion_lines;
229 for (
const auto& assertion : result.assertions) {
230 assertion_lines.push_back(
231 absl::StrCat(assertion.description,
" => ",
232 assertion.passed ?
"PASS" :
"FAIL"));
234 body = absl::StrCat(body,
"\n",
235 absl::StrJoin(assertion_lines,
"\n"));
237 oss <<
"\n <failure message=\"" << EscapeXml(result.message)
238 <<
"\">" << EscapeXml(body) <<
"</failure>";
239 if (!result.logs.empty()) {
240 oss <<
"\n <system-out>" << EscapeXml(JoinLogs(result.logs))
243 oss <<
"\n </testcase>\n";
248 std::string detail = result.message;
249 if (!result.logs.empty()) {
250 detail = absl::StrCat(detail,
"\n", JoinLogs(result.logs));
252 oss <<
"\n <error message=\"" << EscapeXml(result.message)
253 <<
"\">" << EscapeXml(detail) <<
"</error>";
254 oss <<
"\n </testcase>\n";
258 if (!result.logs.empty()) {
259 oss <<
"\n <system-out>" << EscapeXml(JoinLogs(result.logs))
262 oss <<
"\n </testcase>\n";
265 oss <<
"</testsuite>\n";