Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix type of suites and cases returned when iterating xunit2.JUnitXml #143

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions junitparser/junitparser.py
Original file line number Diff line number Diff line change
@@ -495,15 +495,17 @@ class TestSuite(Element):
skipped = IntAttr()
__test__ = False

testcase = TestCase

def __init__(self, name=None):
super().__init__(self._tag)
self.name = name
self.filepath = None

def __iter__(self):
return itertools.chain(
super().iterchildren(TestCase),
(case for suite in super().iterchildren(TestSuite) for case in suite),
super().iterchildren(self.testcase),
(case for suite in super().iterchildren(type(self)) for case in suite),
)

def __len__(self):
@@ -675,7 +677,7 @@ def __init__(self, name=None):
self.name = name

def __iter__(self):
return super().iterchildren(TestSuite)
return super().iterchildren(self.testsuite)

def __len__(self):
return len(list(self.__iter__()))
148 changes: 72 additions & 76 deletions junitparser/xunit2.py
Original file line number Diff line number Diff line change
@@ -19,82 +19,6 @@
T = TypeVar("T")


class TestSuite(junitparser.TestSuite):
"""TestSuite for Pytest, with some different attributes."""

group = junitparser.Attr()
id = junitparser.Attr()
package = junitparser.Attr()
file = junitparser.Attr()
log = junitparser.Attr()
url = junitparser.Attr()
version = junitparser.Attr()

def __iter__(self):
return itertools.chain(
super().iterchildren(TestCase),
(case for suite in super().iterchildren(TestSuite) for case in suite),
)

@property
def system_out(self):
"""<system-out>"""
elem = self.child(junitparser.SystemOut)
if elem is not None:
return elem.text
return None

@system_out.setter
def system_out(self, value: str):
"""<system-out>"""
out = self.child(junitparser.SystemOut)
if out is not None:
out.text = value
else:
out = junitparser.SystemOut(value)
self.append(out)

@property
def system_err(self):
"""<system-err>"""
elem = self.child(junitparser.SystemErr)
if elem is not None:
return elem.text
return None

@system_err.setter
def system_err(self, value: str):
"""<system-err>"""
err = self.child(junitparser.SystemErr)
if err is not None:
err.text = value
else:
err = junitparser.SystemErr(value)
self.append(err)


class JUnitXml(junitparser.JUnitXml):
# Pytest and xunit schema doesn't have "skipped" in testsuites
skipped = None

testsuite = TestSuite

def update_statistics(self):
"""Update test count, time, etc."""
time = 0
tests = failures = errors = 0
for suite in self:
suite.update_statistics()
tests += suite.tests
failures += suite.failures
errors += suite.errors
time += suite.time
self.tests = tests
self.failures = failures
self.errors = errors
self.time = round(time, 3)


class StackTrace(junitparser.System):
_tag = "stackTrace"

@@ -202,3 +126,75 @@ def flaky_errors(self):
def add_rerun_result(self, result: RerunType):
"""Append a rerun result to the testcase. A testcase can have multiple rerun results."""
self.append(result)


class TestSuite(junitparser.TestSuite):
"""TestSuite for Pytest, with some different attributes."""

group = junitparser.Attr()
id = junitparser.Attr()
package = junitparser.Attr()
file = junitparser.Attr()
log = junitparser.Attr()
url = junitparser.Attr()
version = junitparser.Attr()

testcase = TestCase

@property
def system_out(self):
"""<system-out>"""
elem = self.child(junitparser.SystemOut)
if elem is not None:
return elem.text
return None

@system_out.setter
def system_out(self, value: str):
"""<system-out>"""
out = self.child(junitparser.SystemOut)
if out is not None:
out.text = value
else:
out = junitparser.SystemOut(value)
self.append(out)

@property
def system_err(self):
"""<system-err>"""
elem = self.child(junitparser.SystemErr)
if elem is not None:
return elem.text
return None

@system_err.setter
def system_err(self, value: str):
"""<system-err>"""
err = self.child(junitparser.SystemErr)
if err is not None:
err.text = value
else:
err = junitparser.SystemErr(value)
self.append(err)


class JUnitXml(junitparser.JUnitXml):
# Pytest and xunit schema doesn't have "skipped" in testsuites
skipped = None

testsuite = TestSuite

def update_statistics(self):
"""Update test count, time, etc."""
time = 0
tests = failures = errors = 0
for suite in self:
suite.update_statistics()
tests += suite.tests
failures += suite.failures
errors += suite.errors
time += suite.time
self.tests = tests
self.failures = failures
self.errors = errors
self.time = round(time, 3)
29 changes: 28 additions & 1 deletion tests/test_xunit2.py
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ def test_case_fromstring(self):
<system-err>System err</system-err>
</testcase>"""
case = TestCase.fromstring(text)
assert isinstance(case, TestCase)
assert case.name == "testname"
assert isinstance(case.result[0], Failure)
assert case.system_out == "System out"
@@ -103,12 +104,38 @@ def test_init(self):
assert xml.tostring().count(b"skipped") == 1

def test_fromstring(self):
text = """<testsuites><testsuite name="suitename1">
<testcase name="testname1">
</testcase></testsuite>
<testsuite name="suitename2">
<testcase name="testname2"/>
<testcase name="testname3">
</testcase></testsuite></testsuites>"""
xml = JUnitXml.fromstring(text)
assert isinstance(xml, JUnitXml)
suites = list(xml)
assert len(suites) == 2
suite1, suite2 = suites
assert isinstance(suite1, TestSuite)
assert isinstance(suite2, TestSuite)
assert suite1.name == "suitename1"
assert suite2.name == "suitename2"
cases = list(suite2)
assert len(cases) == 2
assert isinstance(cases[0], TestCase)
assert isinstance(cases[1], TestCase)
assert [test.name for test in cases] == ["testname2", "testname3"]

def test_suite_fromstring(self):
text = """<testsuite name="suite name">
<testcase name="test name 1"/>
<testcase name="test name 2"/>
</testsuite>"""
suite = JUnitXml.fromstring(text)
assert isinstance(suite, TestSuite)
assert suite.name == "suite name"
assert len(list(suite)) == 2
cases = list(suite)
assert len(cases) == 2
assert isinstance(cases[0], TestCase)
assert isinstance(cases[1], TestCase)
assert [test.name for test in suite] == ["test name 1", "test name 2"]