Skip to content

Commit e45ea7e

Browse files
SanderVockekris-jusiak
authored andcommitted
Quick fix of JUnit XML generation.
1 parent cce6120 commit e45ea7e

File tree

1 file changed

+68
-42
lines changed

1 file changed

+68
-42
lines changed

include/boost/ut.hpp

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export import std;
8383
#include <utility>
8484
#include <variant>
8585
#include <vector>
86+
#include <fstream>
8687
#if __has_include(<unistd.h>) and __has_include(<sys/wait.h>)
8788
#include <sys/wait.h>
8889
#include <unistd.h>
@@ -1840,11 +1841,17 @@ class reporter_junit {
18401841
auto on(events::summary) -> void {
18411842
std::cout.flush();
18421843
std::cout.rdbuf(cout_save);
1844+
std::ofstream maybe_of;
1845+
if (detail::cfg::output_filename != "") { maybe_of = std::ofstream(detail::cfg::output_filename); }
1846+
18431847
if (report_type_ == JUNIT) {
1844-
print_junit_summary();
1848+
print_junit_summary(detail::cfg::output_filename != "" ? maybe_of : std::cout);
18451849
return;
18461850
}
1847-
print_console_summary();
1851+
print_console_summary(
1852+
detail::cfg::output_filename != "" ? maybe_of : std::cout,
1853+
detail::cfg::output_filename != "" ? maybe_of : std::cerr
1854+
);
18481855
}
18491856

18501857
protected:
@@ -1860,10 +1867,10 @@ class reporter_junit {
18601867
}
18611868
}
18621869

1863-
void print_console_summary() {
1870+
void print_console_summary(std::ostream &out_stream, std::ostream &err_stream) {
18641871
for (const auto& [suite_name, suite_result] : results_) {
18651872
if (suite_result.fails) {
1866-
std::cerr
1873+
err_stream
18671874
<< "\n========================================================"
18681875
"=======================\n"
18691876
<< "Suite " << suite_name //
@@ -1875,7 +1882,7 @@ class reporter_junit {
18751882
<< color_.none << '\n';
18761883
std::cerr << std::endl;
18771884
} else {
1878-
std::cout << color_.pass << "Suite '" << suite_name
1885+
out_stream << color_.pass << "Suite '" << suite_name
18791886
<< "': all tests passed" << color_.none << " ("
18801887
<< suite_result.assertions << " asserts in "
18811888
<< suite_result.n_tests << " tests)\n";
@@ -1889,58 +1896,77 @@ class reporter_junit {
18891896
}
18901897
}
18911898

1892-
void print_junit_summary() {
1893-
// mock junit output:
1894-
std::cout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
1895-
for (const auto& [suite_name, suite_result] : results_) {
1896-
std::cout << "<testsuites";
1897-
std::cout << " classname=\"" << detail::cfg::executable_name << '\"';
1898-
std::cout << " name=\"" << suite_name << '\"';
1899-
std::cout << " tests=\"" << suite_result.n_tests << '\"';
1900-
std::cout << " errors=\"" << suite_result.fails << '\"';
1901-
std::cout << " failures=\"" << suite_result.fails << '\"';
1902-
std::cout << " skipped=\"" << suite_result.skipped << '\"';
1899+
void print_junit_summary(std::ostream &stream) {
1900+
// aggregate results
1901+
size_t n_tests=0, n_fails=0;
1902+
double total_time = 0.0;
1903+
auto suite_time = [](auto const& suite_result) {
19031904
std::int64_t time_ms =
19041905
std::chrono::duration_cast<std::chrono::milliseconds>(
19051906
suite_result.run_stop - suite_result.run_start)
19061907
.count();
1907-
std::cout << " time=\"" << (static_cast<double>(time_ms) / 1000.0)
1908-
<< '\"';
1909-
std::cout << " version=\"" << BOOST_UT_VERSION << "\" />\n";
1910-
print_result(suite_name, " ", suite_result);
1911-
std::cout << "</testsuites>\n";
1912-
std::cout.flush();
1908+
return static_cast<double>(time_ms) / 1000.0;
1909+
};
1910+
for (const auto& [suite_name, suite_result] : results_) {
1911+
n_tests += suite_result.assertions;
1912+
n_fails += suite_result.fails;
1913+
total_time += suite_time(suite_result);
19131914
}
1914-
}
1915-
void print_result(const std::string& suite_name, std::string indent,
1915+
1916+
// mock junit output:
1917+
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
1918+
stream << "<testsuites";
1919+
stream << " name=\"all\"";
1920+
stream << " tests=\"" << n_tests << '\"';
1921+
stream << " failures=\"" << n_fails << '\"';
1922+
stream << " time=\"" << total_time << '\"';
1923+
stream << ">\n";
1924+
1925+
for (const auto& [suite_name, suite_result] : results_) {
1926+
stream << "<testsuite";
1927+
stream << " classname=\"" << detail::cfg::executable_name << '\"';
1928+
stream << " name=\"" << suite_name << '\"';
1929+
stream << " tests=\"" << suite_result.assertions << '\"';
1930+
stream << " errors=\"" << suite_result.fails << '\"';
1931+
stream << " failures=\"" << suite_result.fails << '\"';
1932+
stream << " skipped=\"" << suite_result.skipped << '\"';
1933+
stream << " time=\"" << suite_time(suite_result) << '\"';
1934+
stream << " version=\"" << BOOST_UT_VERSION << "\">\n";
1935+
print_result(stream, suite_name, " ", suite_result);
1936+
stream << "</testsuite>\n";
1937+
stream.flush();
1938+
}
1939+
stream << "</testsuites>";
1940+
}
1941+
void print_result(std::ostream &stream, const std::string& suite_name, std::string indent,
19161942
const test_result& parent) {
19171943
for (const auto& [name, result] : *parent.nested_tests) {
1918-
std::cout << indent;
1919-
std::cout << "<testcase classname=\"" << result.suite_name << '\"';
1920-
std::cout << " name=\"" << name << '\"';
1921-
std::cout << " tests=\"" << result.assertions << '\"';
1922-
std::cout << " errors=\"" << result.fails << '\"';
1923-
std::cout << " failures=\"" << result.fails << '\"';
1924-
std::cout << " skipped=\"" << result.skipped << '\"';
1944+
stream << indent;
1945+
stream << "<testcase classname=\"" << result.suite_name << '\"';
1946+
stream << " name=\"" << name << '\"';
1947+
stream << " tests=\"" << result.assertions << '\"';
1948+
stream << " errors=\"" << result.fails << '\"';
1949+
stream << " failures=\"" << result.fails << '\"';
1950+
stream << " skipped=\"" << result.skipped << '\"';
19251951
std::int64_t time_ms =
19261952
std::chrono::duration_cast<std::chrono::milliseconds>(
19271953
result.run_stop - result.run_start)
19281954
.count();
1929-
std::cout << " time=\"" << (static_cast<double>(time_ms) / 1000.0)
1955+
stream << " time=\"" << (static_cast<double>(time_ms) / 1000.0)
19301956
<< "\"";
1931-
std::cout << " status=\"" << result.status << '\"';
1957+
stream << " status=\"" << result.status << '\"';
19321958
if (result.report_string.empty() && result.nested_tests->empty()) {
1933-
std::cout << " />\n";
1959+
stream << " />\n";
19341960
} else if (!result.nested_tests->empty()) {
1935-
std::cout << " />\n";
1936-
print_result(suite_name, indent + " ", result);
1937-
std::cout << indent << "</testcase>\n";
1961+
stream << " />\n";
1962+
print_result(stream, suite_name, indent + " ", result);
1963+
stream << indent << "</testcase>\n";
19381964
} else if (!result.report_string.empty()) {
1939-
std::cout << ">\n";
1940-
std::cout << indent << indent << "<system-out>\n";
1941-
std::cout << result.report_string << "\n";
1942-
std::cout << indent << indent << "</system-out>\n";
1943-
std::cout << indent << "</testcase>\n";
1965+
stream << ">\n";
1966+
stream << indent << indent << "<system-out>\n";
1967+
stream << result.report_string << "\n";
1968+
stream << indent << indent << "</system-out>\n";
1969+
stream << indent << "</testcase>\n";
19441970
}
19451971
}
19461972
}

0 commit comments

Comments
 (0)