Skip to content

Commit 9f83e22

Browse files
committed
Better output for junit formatter
1 parent 4b4d06a commit 9f83e22

File tree

1 file changed

+52
-12
lines changed

1 file changed

+52
-12
lines changed

Diff for: library/test/src/formatters/junit.rs

+52-12
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66
console::{ConsoleTestState, OutputLocation},
77
test_result::TestResult,
88
time,
9-
types::TestDesc,
9+
types::{TestDesc, TestType},
1010
};
1111

1212
pub struct JunitFormatter<T> {
@@ -70,13 +70,15 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
7070
state.failed, state.total, state.ignored
7171
))?;
7272
for (desc, result, duration) in std::mem::replace(&mut self.results, Vec::new()) {
73+
let (class_name, test_name) = parse_class_name(&desc);
7374
match result {
7475
TestResult::TrIgnored => { /* no-op */ }
7576
TestResult::TrFailed => {
7677
self.write_message(&*format!(
77-
"<testcase classname=\"test.global\" \
78+
"<testcase classname=\"{}\" \
7879
name=\"{}\" time=\"{}\">",
79-
desc.name.as_slice(),
80+
class_name,
81+
test_name,
8082
duration.as_secs()
8183
))?;
8284
self.write_message("<failure type=\"assert\"/>")?;
@@ -85,9 +87,10 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
8587

8688
TestResult::TrFailedMsg(ref m) => {
8789
self.write_message(&*format!(
88-
"<testcase classname=\"test.global\" \
90+
"<testcase classname=\"{}\" \
8991
name=\"{}\" time=\"{}\">",
90-
desc.name.as_slice(),
92+
class_name,
93+
test_name,
9194
duration.as_secs()
9295
))?;
9396
self.write_message(&*format!("<failure message=\"{}\" type=\"assert\"/>", m))?;
@@ -96,9 +99,10 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
9699

97100
TestResult::TrTimedFail => {
98101
self.write_message(&*format!(
99-
"<testcase classname=\"test.global\" \
102+
"<testcase classname=\"{}\" \
100103
name=\"{}\" time=\"{}\">",
101-
desc.name.as_slice(),
104+
class_name,
105+
test_name,
102106
duration.as_secs()
103107
))?;
104108
self.write_message("<failure type=\"timeout\"/>")?;
@@ -107,18 +111,18 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
107111

108112
TestResult::TrBench(ref b) => {
109113
self.write_message(&*format!(
110-
"<testcase classname=\"benchmark.global\" \
114+
"<testcase classname=\"benchmark::{}\" \
111115
name=\"{}\" time=\"{}\" />",
112-
desc.name.as_slice(),
113-
b.ns_iter_summ.sum
116+
class_name, test_name, b.ns_iter_summ.sum
114117
))?;
115118
}
116119

117120
TestResult::TrOk | TestResult::TrAllowedFail => {
118121
self.write_message(&*format!(
119-
"<testcase classname=\"test.global\" \
122+
"<testcase classname=\"{}\" \
120123
name=\"{}\" time=\"{}\"/>",
121-
desc.name.as_slice(),
124+
class_name,
125+
test_name,
122126
duration.as_secs()
123127
))?;
124128
}
@@ -132,3 +136,39 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
132136
Ok(state.failed == 0)
133137
}
134138
}
139+
140+
fn parse_class_name(desc: &TestDesc) -> (String, String) {
141+
match desc.test_type {
142+
TestType::UnitTest => parse_class_name_unit(desc),
143+
TestType::DocTest => parse_class_name_doc(desc),
144+
TestType::IntegrationTest => parse_class_name_integration(desc),
145+
TestType::Unknown => (String::from("unknown"), String::from(desc.name.as_slice())),
146+
}
147+
}
148+
149+
fn parse_class_name_unit(desc: &TestDesc) -> (String, String) {
150+
// Module path => classname
151+
// Function name => name
152+
let module_segments: Vec<&str> = desc.name.as_slice().split("::").collect();
153+
let (class_name, test_name) = match module_segments[..] {
154+
[test] => (String::from("crate"), String::from(test)),
155+
[ref path @ .., test] => (path.join("::"), String::from(test)),
156+
[..] => unreachable!(),
157+
};
158+
(class_name, test_name)
159+
}
160+
161+
fn parse_class_name_doc(desc: &TestDesc) -> (String, String) {
162+
// File path => classname
163+
// Line # => test name
164+
let segments: Vec<&str> = desc.name.as_slice().split(" - ").collect();
165+
let (class_name, test_name) = match segments[..] {
166+
[file, line] => (String::from(file.trim()), String::from(line.trim())),
167+
[..] => unreachable!(),
168+
};
169+
(class_name, test_name)
170+
}
171+
172+
fn parse_class_name_integration(desc: &TestDesc) -> (String, String) {
173+
(String::from("integration"), String::from(desc.name.as_slice()))
174+
}

0 commit comments

Comments
 (0)