@@ -6,6 +6,7 @@ _BASHUNIT_REPORTS_TEST_NAMES=()
66_BASHUNIT_REPORTS_TEST_STATUSES=()
77_BASHUNIT_REPORTS_TEST_DURATIONS=()
88_BASHUNIT_REPORTS_TEST_ASSERTIONS=()
9+ _BASHUNIT_REPORTS_TEST_FAILURES=()
910
1011function bashunit::reports::add_test_snapshot() {
1112 bashunit::reports::add_test " $1 " " $2 " " $3 " " $4 " " snapshot"
@@ -24,7 +25,7 @@ function bashunit::reports::add_test_passed() {
2425}
2526
2627function bashunit::reports::add_test_failed() {
27- bashunit::reports::add_test " $1 " " $2 " " $3 " " $4 " " failed"
28+ bashunit::reports::add_test " $1 " " $2 " " $3 " " $4 " " failed" " $5 "
2829}
2930
3031function bashunit::reports::add_test() {
@@ -36,45 +37,69 @@ function bashunit::reports::add_test() {
3637 local duration=" $3 "
3738 local assertions=" $4 "
3839 local status=" $5 "
40+ local failure_message=" ${6:- } "
3941
4042 _BASHUNIT_REPORTS_TEST_FILES[${# _BASHUNIT_REPORTS_TEST_FILES[@]} ]=" $file "
4143 _BASHUNIT_REPORTS_TEST_NAMES[${# _BASHUNIT_REPORTS_TEST_NAMES[@]} ]=" $test_name "
4244 _BASHUNIT_REPORTS_TEST_STATUSES[${# _BASHUNIT_REPORTS_TEST_STATUSES[@]} ]=" $status "
4345 _BASHUNIT_REPORTS_TEST_ASSERTIONS[${# _BASHUNIT_REPORTS_TEST_ASSERTIONS[@]} ]=" $assertions "
4446 _BASHUNIT_REPORTS_TEST_DURATIONS[${# _BASHUNIT_REPORTS_TEST_DURATIONS[@]} ]=" $duration "
47+ _BASHUNIT_REPORTS_TEST_FAILURES[${# _BASHUNIT_REPORTS_TEST_FAILURES[@]} ]=" $failure_message "
48+ }
49+
50+ function bashunit::reports::__xml_escape() {
51+ local text=" $1 "
52+ # Strip ANSI escape sequences and control characters invalid in XML 1.0,
53+ # then escape XML special characters (& first to avoid double-escaping)
54+ echo " $text " \
55+ | sed -e ' s/\x1b\[[0-9;]*[a-zA-Z]//g' \
56+ | tr -d ' \000-\010\013\014\016-\037' \
57+ | sed -e ' s/&/\&/g' -e ' s/</\</g' -e ' s/>/\>/g' -e ' s/"/\"/g' -e " s/'/\'/g"
4558}
4659
4760function bashunit::reports::generate_junit_xml() {
4861 local output_file=" $1 "
4962
50- local test_passed=$( bashunit::state::get_tests_passed)
5163 local tests_skipped=$( bashunit::state::get_tests_skipped)
5264 local tests_incomplete=$( bashunit::state::get_tests_incomplete)
53- local tests_snapshot=$( bashunit::state::get_tests_snapshot)
5465 local tests_failed=$( bashunit::state::get_tests_failed)
55- local time=$( bashunit::clock::total_runtime_in_milliseconds)
66+ local time_ms=$( bashunit::clock::total_runtime_in_milliseconds)
67+ local time
68+ time=$( LC_ALL=C awk -v ms=" $time_ms " ' BEGIN {printf "%.3f", ms/1000}' )
5669
5770 {
5871 echo " <?xml version=\" 1.0\" encoding=\" UTF-8\" ?>"
5972 echo " <testsuites>"
6073 echo " <testsuite name=\" bashunit\" tests=\" ${# _BASHUNIT_REPORTS_TEST_NAMES[@]} \" "
61- echo " passed= \" $test_passed \" failures=\" $tests_failed \" incomplete =\" $tests_incomplete \" "
62- echo " skipped=\" $tests_skipped \" snapshot= \" $tests_snapshot \" "
74+ echo " failures=\" $tests_failed \" errors =\" 0 \" "
75+ echo " skipped=\" $(( tests_skipped + tests_incomplete )) \" "
6376 echo " time=\" $time \" >"
6477
6578 local i
6679 for i in " ${! _BASHUNIT_REPORTS_TEST_NAMES[@]} " ; do
6780 local file=" ${_BASHUNIT_REPORTS_TEST_FILES[$i]:- } "
6881 local name=" ${_BASHUNIT_REPORTS_TEST_NAMES[$i]:- } "
69- local assertions=" ${_BASHUNIT_REPORTS_TEST_ASSERTIONS[$i]:- } "
7082 local status=" ${_BASHUNIT_REPORTS_TEST_STATUSES[$i]:- } "
71- local test_time=" ${_BASHUNIT_REPORTS_TEST_DURATIONS[$i]:- } "
83+ local test_time_ms=" ${_BASHUNIT_REPORTS_TEST_DURATIONS[$i]:- } "
84+ local failure_message=" ${_BASHUNIT_REPORTS_TEST_FAILURES[$i]:- } "
85+ local test_time
86+ test_time=$( LC_ALL=C awk -v ms=" $test_time_ms " ' BEGIN {printf "%.3f", ms/1000}' )
7287
7388 echo " <testcase file=\" $file \" "
7489 echo " name=\" $name \" "
75- echo " status=\" $status \" "
76- echo " assertions=\" $assertions \" "
7790 echo " time=\" $test_time \" >"
91+
92+ # Add failure element for failed tests with actual failure message
93+ if [[ " $status " == " failed" ]]; then
94+ local escaped_message
95+ escaped_message=$( bashunit::reports::__xml_escape " $failure_message " )
96+ echo " <failure message=\" Test failed\" >$escaped_message </failure>"
97+ elif [[ " $status " == " skipped" ]]; then
98+ echo " <skipped/>"
99+ elif [[ " $status " == " incomplete" ]]; then
100+ echo " <skipped message=\" Test incomplete\" />"
101+ fi
102+
78103 echo " </testcase>"
79104 done
80105
0 commit comments