Skip to content

Commit

Permalink
Merge pull request #24 from codecov/joseph/control-char-splitting
Browse files Browse the repository at this point in the history
feat: use ascii control char US to separate the class name and test name when parsing junit
  • Loading branch information
joseph-sentry authored Jun 19, 2024
2 parents 5fc0212 + 1507de2 commit 26bae46
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 30 deletions.
26 changes: 12 additions & 14 deletions src/junit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,22 @@ use crate::testrun::{Outcome, Testrun};
// from https://gist.github.com/scott-codecov/311c174ecc7de87f7d7c50371c6ef927#file-cobertura-rs-L18-L31
fn attributes_map(attributes: Attributes) -> Result<HashMap<String, String>, pyo3::PyErr> {
let mut attr_map = HashMap::new();
for attribute in attributes {
if let Ok(attr) = attribute {
let bytes = attr.value.into_owned();
let value = String::from_utf8(bytes)?;
let key = String::from_utf8(attr.key.into_inner().to_vec())?;
attr_map.insert(key, value);
}
for attribute in attributes.flatten() {
let bytes = attribute.value.into_owned();
let value = String::from_utf8(bytes)?;
let key = String::from_utf8(attribute.key.into_inner().to_vec())?;
attr_map.insert(key, value);
}
Ok(attr_map)
}

fn populate(attr_hm: &HashMap<String, String>, testsuite: String) -> Result<Testrun, pyo3::PyErr> {
let name = format!(
"{}::{}",
"{}{}{}",
attr_hm
.get("classname")
.ok_or(ParserError::new_err("No classname found"))?,
'\x1f',
attr_hm
.get("name")
.ok_or(ParserError::new_err("No name found"))?
Expand Down Expand Up @@ -107,7 +106,7 @@ pub fn parse_junit_xml(file_bytes: Vec<u8>) -> PyResult<Vec<Testrun>> {

curr_testsuite = attr_hm?
.get("name")
.ok_or(ParserError::new_err(format!("Error getting name",)))?
.ok_or(ParserError::new_err("Error getting name".to_string()))?
.to_string();
}
_ => {}
Expand All @@ -123,15 +122,14 @@ pub fn parse_junit_xml(file_bytes: Vec<u8>) -> PyResult<Vec<Testrun>> {
b"failure" => in_failure = false,
_ => (),
},
Ok(Event::Empty(e)) => match e.name().as_ref() {
b"testcase" => {
Ok(Event::Empty(e)) => {
if e.name().as_ref() == b"testcase" {
let attr_hm = attributes_map(e.attributes());
list_of_test_runs.push(populate(&attr_hm?, curr_testsuite.clone())?);
}
_ => (),
},
}
Ok(Event::Text(x)) => {
if in_failure == true {
if in_failure {
let mut testrun = saved_testrun
.ok_or(ParserError::new_err("Error accessing saved testrun"))?;

Expand Down
31 changes: 15 additions & 16 deletions tests/test_junit.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from test_results_parser import parse_junit_xml, Testrun, Outcome
from test_results_parser import Outcome, Testrun, parse_junit_xml


class TestParsers:
Expand All @@ -10,7 +10,7 @@ class TestParsers:
"./tests/junit.xml",
[
Testrun(
"tests.test_parsers.TestParsers::test_junit[junit.xml--True]",
"tests.test_parsers.TestParsers\x1ftest_junit[junit.xml--True]",
0.001,
Outcome.Failure,
"pytest",
Expand All @@ -32,7 +32,7 @@ def test_junit(self, filename, expected, check):
tests/test_parsers.py:16: AssertionError""",
),
Testrun(
"tests.test_parsers.TestParsers::test_junit[jest-junit.xml--False]",
"tests.test_parsers.TestParsers\x1ftest_junit[jest-junit.xml--False]",
0.064,
Outcome.Pass,
"pytest",
Expand All @@ -44,28 +44,28 @@ def test_junit(self, filename, expected, check):
"./tests/jest-junit.xml",
[
Testrun(
"Title when rendered renders pull title::Title when rendered renders pull title",
"Title when rendered renders pull title\x1fTitle when rendered renders pull title",
0.036,
Outcome.Pass,
"Title",
None,
),
Testrun(
"Title when rendered renders pull author::Title when rendered renders pull author",
"Title when rendered renders pull author\x1fTitle when rendered renders pull author",
0.005,
Outcome.Pass,
"Title",
None,
),
Testrun(
"Title when rendered renders pull updatestamp::Title when rendered renders pull updatestamp",
"Title when rendered renders pull updatestamp\x1fTitle when rendered renders pull updatestamp",
0.002,
Outcome.Pass,
"Title",
None,
),
Testrun(
"Title when rendered for first pull request renders pull title::Title when rendered for first pull request renders pull title",
"Title when rendered for first pull request renders pull title\x1fTitle when rendered for first pull request renders pull title",
0.006,
Outcome.Pass,
"Title",
Expand All @@ -77,15 +77,15 @@ def test_junit(self, filename, expected, check):
"./tests/vitest-junit.xml",
[
Testrun(
"__tests__/test-file-1.test.ts::first test file &gt; 2 + 2 should equal 4",
"__tests__/test-file-1.test.ts\x1ffirst test file &gt; 2 + 2 should equal 4",
0.01,
Outcome.Failure,
"__tests__/test-file-1.test.ts",
"""AssertionError: expected 5 to be 4 // Object.is equality
❯ __tests__/test-file-1.test.ts:20:28""",
),
Testrun(
"__tests__/test-file-1.test.ts::first test file &gt; 4 - 2 should equal 2",
"__tests__/test-file-1.test.ts\x1ffirst test file &gt; 4 - 2 should equal 2",
0,
Outcome.Pass,
"__tests__/test-file-1.test.ts",
Expand All @@ -97,20 +97,20 @@ def test_junit(self, filename, expected, check):
"./tests/empty_failure.junit.xml",
[
Testrun(
"test.test::test.test works",
"test.test\x1ftest.test works",
0.234,
Outcome.Pass,
"test",
None
None,
),
Testrun(
"test.test::test.test fails",
Testrun(
"test.test\x1ftest.test fails",
1,
Outcome.Failure,
"test",
"TestError"
"TestError",
),
]
],
),
],
)
Expand All @@ -120,4 +120,3 @@ def test_junit(self, filename, expected):
assert len(res) == len(expected)
for restest, extest in zip(res, expected):
assert restest == extest

0 comments on commit 26bae46

Please sign in to comment.