Skip to content

Commit

Permalink
Merge pull request #38 from b4nst/feat/fix-testcase-stdout-and-add-tr…
Browse files Browse the repository at this point in the history
…ace-property

Feat/fix testcase stdout and add trace property
  • Loading branch information
bachp authored Dec 7, 2023
2 parents 68c34fb + 3015498 commit 14883cd
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 34 deletions.
23 changes: 23 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ time = { version = "0.3.4", features = ["formatting", "macros"] }
[dev-dependencies]
doc-comment = "0.3.3"
once_cell = "1.14"
pretty_assertions = "1.4.0"
regex = "1.6"
26 changes: 24 additions & 2 deletions src/collections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,16 @@ pub struct TestCase {
pub enum TestResult {
Success,
Skipped,
Error { type_: String, message: String },
Failure { type_: String, message: String },
Error {
type_: String,
message: String,
cause: Option<String>,
},
Failure {
type_: String,
message: String,
cause: Option<String>,
},
}

impl TestCase {
Expand Down Expand Up @@ -202,6 +210,7 @@ impl TestCase {
result: TestResult::Error {
type_: type_.into(),
message: message.into(),
cause: None,
},
classname: None,
filepath: None,
Expand All @@ -225,6 +234,7 @@ impl TestCase {
result: TestResult::Failure {
type_: type_.into(),
message: message.into(),
cause: None,
},
classname: None,
filepath: None,
Expand Down Expand Up @@ -297,6 +307,18 @@ impl TestCaseBuilder {
self
}

/// Set the `result.trace` for the `TestCase`
///
/// It has no effect on successful `TestCase`s.
pub fn set_trace(&mut self, trace: &str) -> &mut Self {
match self.testcase.result {
TestResult::Error { ref mut cause, .. } => *cause = Some(trace.to_owned()),
TestResult::Failure { ref mut cause, .. } => *cause = Some(trace.to_owned()),
_ => {}
}
self
}

/// Creates a new TestCaseBuilder for an erroneous `TestCase`
///
/// An erroneous `TestCase` is one that encountered an unexpected error condition.
Expand Down
73 changes: 71 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ mod tests {
datetime, Duration, Report, ReportBuilder, TestCase, TestCaseBuilder, TestSuite,
TestSuiteBuilder,
};
use pretty_assertions::assert_eq;

#[test]
fn empty_testsuites() {
Expand Down Expand Up @@ -360,10 +361,78 @@ mod tests {
<system-out><![CDATA[Some sysout message]]></system-out>\
</testcase>\
<testcase name=\"error test\" time=\"5\">\
<error type=\"git error\" message=\"unable to fetch\"><![CDATA[Some syserror message]]></error>\
<error type=\"git error\" message=\"unable to fetch\"/>\
<system-err><![CDATA[Some syserror message]]></system-err>\
</testcase>\
<testcase name=\"failure test\" time=\"10\">\
<failure type=\"assert_eq\" message=\"not equal\"/>\
<system-out><![CDATA[System out or error message]]></system-out>\
<system-err><![CDATA[Another system error message]]></system-err>\
</testcase>\
</testsuite>\
</testsuites>",
);
}

#[test]
fn test_cases_with_trace() {
let timestamp = datetime!(1970-01-01 01:01 UTC);

let test_success = TestCaseBuilder::success("good test", Duration::milliseconds(15001))
.set_classname("MyClass")
.set_filepath("./foo.rs")
.set_trace("Some trace message") // This should be ignored
.build();
let test_error = TestCaseBuilder::error(
"error test",
Duration::seconds(5),
"git error",
"unable to fetch",
)
.set_trace("Some error trace")
.build();
let test_failure = TestCaseBuilder::failure(
"failure test",
Duration::seconds(10),
"assert_eq",
"not equal",
)
.set_trace("Some failure trace")
.build();

let ts1 = TestSuiteBuilder::new("ts1")
.set_timestamp(timestamp)
.build();
let ts2 = TestSuiteBuilder::new("ts2")
.set_timestamp(timestamp)
.add_testcase(test_success)
.add_testcase(test_error)
.add_testcase(test_failure)
.build();

let r = ReportBuilder::new()
.add_testsuite(ts1)
.add_testsuite(ts2)
.build();

let mut out: Vec<u8> = Vec::new();

r.write_xml(&mut out).unwrap();

// language=xml
assert_eq!(
String::from_utf8(out).unwrap(),
"\
<?xml version=\"1.0\" encoding=\"utf-8\"?>\
<testsuites>\
<testsuite id=\"0\" name=\"ts1\" package=\"testsuite/ts1\" tests=\"0\" errors=\"0\" failures=\"0\" hostname=\"localhost\" timestamp=\"1970-01-01T01:01:00Z\" time=\"0\"/>\
<testsuite id=\"1\" name=\"ts2\" package=\"testsuite/ts2\" tests=\"3\" errors=\"1\" failures=\"1\" hostname=\"localhost\" timestamp=\"1970-01-01T01:01:00Z\" time=\"30.001\">\
<testcase name=\"good test\" time=\"15.001\" classname=\"MyClass\" file=\"./foo.rs\"/>\
<testcase name=\"error test\" time=\"5\">\
<error type=\"git error\" message=\"unable to fetch\"><![CDATA[Some error trace]]></error>\
</testcase>\
<testcase name=\"failure test\" time=\"10\">\
<failure type=\"assert_eq\" message=\"not equal\"><![CDATA[System out or error message]]><![CDATA[Another system error message]]></failure>\
<failure type=\"assert_eq\" message=\"not equal\"><![CDATA[Some failure trace]]></failure>\
</testcase>\
</testsuite>\
</testsuites>",
Expand Down
48 changes: 18 additions & 30 deletions src/reports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,36 +119,22 @@ impl TestCase {
},
|w| {
match self.result {
TestResult::Success => w
.write_opt(self.system_out.as_ref(), |w, out| {
w.create_element("system-out")
.write_cdata_content(BytesCData::new(out.as_str()))
})?
.write_opt(self.system_err.as_ref(), |w, err| {
w.create_element("system-err")
.write_cdata_content(BytesCData::new(err.as_str()))
}),
TestResult::Success => Ok(w),
TestResult::Error {
ref type_,
ref message,
ref cause,
} => w
.create_element("error")
.with_attributes([
("type", type_.as_str()),
("message", message.as_str()),
])
.write_empty_or_inner(
|_| self.system_out.is_none() && self.system_err.is_none(),
|_| cause.is_none(),
|w| {
w.write_opt(self.system_out.as_ref(), |w, stdout| {
let data = strip_ansi_escapes::strip(stdout);
w.write_event(Event::CData(BytesCData::new(
String::from_utf8_lossy(&data),
)))
.map(|_| w)
})?
.write_opt(self.system_err.as_ref(), |w, stderr| {
let data = strip_ansi_escapes::strip(stderr);
w.write_opt(cause.as_ref(), |w, cause| {
let data = BytesCData::new(cause.as_str());
w.write_event(Event::CData(BytesCData::new(
String::from_utf8_lossy(&data),
)))
Expand All @@ -160,24 +146,18 @@ impl TestCase {
TestResult::Failure {
ref type_,
ref message,
ref cause,
} => w
.create_element("failure")
.with_attributes([
("type", type_.as_str()),
("message", message.as_str()),
])
.write_empty_or_inner(
|_| self.system_out.is_none() && self.system_err.is_none(),
|_| cause.is_none(),
|w| {
w.write_opt(self.system_out.as_ref(), |w, stdout| {
let data = strip_ansi_escapes::strip(stdout);
w.write_event(Event::CData(BytesCData::new(
String::from_utf8_lossy(&data),
)))
.map(|_| w)
})?
.write_opt(self.system_err.as_ref(), |w, stderr| {
let data = strip_ansi_escapes::strip(stderr);
w.write_opt(cause.as_ref(), |w, cause| {
let data = BytesCData::new(cause.as_str());
w.write_event(Event::CData(BytesCData::new(
String::from_utf8_lossy(&data),
)))
Expand All @@ -187,7 +167,15 @@ impl TestCase {
},
),
TestResult::Skipped => w.create_element("skipped").write_empty(),
}
}?
.write_opt(self.system_out.as_ref(), |w, out| {
w.create_element("system-out")
.write_cdata_content(BytesCData::new(out.as_str()))
})?
.write_opt(self.system_err.as_ref(), |w, err| {
w.create_element("system-err")
.write_cdata_content(BytesCData::new(err.as_str()))
})
.map(drop)
},
)
Expand Down

0 comments on commit 14883cd

Please sign in to comment.