From 6b8173839663d3a20b37095a89518a1e1c0e5ae5 Mon Sep 17 00:00:00 2001 From: joseph-sentry Date: Thu, 19 Dec 2024 15:07:24 -0500 Subject: [PATCH 1/2] feat: update JUnit parsing we want to handle when the skip or error is an empty XML element we also want to handle when the error has a message in the same way that a failure has a message --- src/junit.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/junit.rs b/src/junit.rs index 1610d8b..9c4c424 100644 --- a/src/junit.rs +++ b/src/junit.rs @@ -98,7 +98,7 @@ pub fn parse_junit_xml(file_bytes: &[u8]) -> PyResult { Ok(thing) } -fn get_position_info(input: &[u8], byte_offset: usize) -> (usize, usize) { +pub fn get_position_info(input: &[u8], byte_offset: usize) -> (usize, usize) { let mut line = 1; let mut last_newline = 0; @@ -119,6 +119,7 @@ fn use_reader(reader: &mut Reader<&[u8]>) -> PyResult { let mut saved_testrun: Option = None; let mut in_failure: bool = false; + let mut in_error: bool = false; let mut framework: Option = None; @@ -168,6 +169,11 @@ fn use_reader(reader: &mut Reader<&[u8]>) -> PyResult { .as_mut() .ok_or_else(|| ParserError::new_err("Error accessing saved testrun"))?; testrun.outcome = Outcome::Error; + + testrun.failure_message = get_attribute(&e, "message")? + .map(|failure_message| unescape_str(&failure_message).into()); + + in_error = true; } b"failure" => { let testrun = saved_testrun @@ -200,6 +206,7 @@ fn use_reader(reader: &mut Reader<&[u8]>) -> PyResult { testruns.push(testrun); } b"failure" => in_failure = false, + b"error" => in_error = false, b"testsuite" => { testsuite_times.pop(); testsuite_names.pop(); @@ -231,10 +238,25 @@ fn use_reader(reader: &mut Reader<&[u8]>) -> PyResult { testrun.failure_message = get_attribute(&e, "message")? .map(|failure_message| unescape_str(&failure_message).into()); } + b"skipped" => { + let testrun = saved_testrun + .as_mut() + .ok_or_else(|| ParserError::new_err("Error accessing saved testrun"))?; + testrun.outcome = Outcome::Skip; + } + b"error" => { + let testrun = saved_testrun + .as_mut() + .ok_or_else(|| ParserError::new_err("Error accessing saved testrun"))?; + testrun.outcome = Outcome::Error; + + testrun.failure_message = get_attribute(&e, "message")? + .map(|failure_message| unescape_str(&failure_message).into()); + } _ => {} }, Event::Text(mut xml_failure_message) => { - if in_failure { + if in_failure || in_error { let testrun = saved_testrun .as_mut() .ok_or_else(|| ParserError::new_err("Error accessing saved testrun"))?; From b29e70144b9065bbb35d1105fead65aad1b01f8c Mon Sep 17 00:00:00 2001 From: joseph-sentry Date: Thu, 19 Dec 2024 16:55:49 -0500 Subject: [PATCH 2/2] test: add tests --- tests/skip-error.junit.xml | 15 +++++++++++++++ tests/test_junit.py | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 tests/skip-error.junit.xml diff --git a/tests/skip-error.junit.xml b/tests/skip-error.junit.xml new file mode 100644 index 0000000..4ac747f --- /dev/null +++ b/tests/skip-error.junit.xml @@ -0,0 +1,15 @@ + + + + + hello world + + + + + + + + + \ No newline at end of file diff --git a/tests/test_junit.py b/tests/test_junit.py index 64152cd..09cc2d0 100644 --- a/tests/test_junit.py +++ b/tests/test_junit.py @@ -283,6 +283,44 @@ def test_junit(self, filename, expected, check): [], ), ), + ( + "./tests/skip-error.junit.xml", + ParsingInfo( + Framework.Pytest, + [ + Testrun( + name="test_subtract", + classname="tests.test_math.TestMath", + duration=0.1, + outcome=Outcome.Error, + testsuite="pytest", + failure_message="hello world", + filename=None, + computed_name="tests.test_math.TestMath::test_subtract", + ), + Testrun( + name="test_multiply", + classname="tests.test_math.TestMath", + duration=0.1, + outcome=Outcome.Error, + testsuite="pytest", + failure_message=None, + filename=None, + computed_name="tests.test_math.TestMath::test_multiply", + ), + Testrun( + name="test_add", + classname="tests.test_math.TestMath", + duration=0.1, + outcome=Outcome.Skip, + testsuite="pytest", + failure_message=None, + filename=None, + computed_name="tests.test_math.TestMath::test_add", + ) + ], + ), + ), ], ) def test_junit(self, filename, expected):