Skip to content

Commit

Permalink
support pytest
Browse files Browse the repository at this point in the history
  • Loading branch information
weiwei committed Apr 20, 2023
1 parent 9d96bff commit da64237
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 18 deletions.
2 changes: 1 addition & 1 deletion junitparser/flavors/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import pytest_xml

126 changes: 109 additions & 17 deletions junitparser/flavors/pytest_xml.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
"""
>>> xml = PytestXml();
>>> xml.
"""

from junitparser.junitparser import JUnitXml, JUnitXmlError, TestSuite, Attr, IntAttr, \
SystemOut, SystemErr
import itertools
from junitparser.junitparser import JUnitXml, JUnitXmlError, Result, TestSuite as OrigTestSuite, Attr, \
SystemOut, SystemErr, TestCase as OrigTestCase, System


class PytestXml(JUnitXml):
Expand All @@ -14,13 +9,13 @@ class PytestXml(JUnitXml):
def __init__(self, name=None):
super().__init__(name)
def __iter__(self):
return super(JUnitXml, self).iterchildren(PyTestSuite)
return super().iterchildren(TestSuite)
def __iadd__(self, other):
if other._elem.tag == "testsuites":
for suite in other:
self.add_testsuite(suite)
elif other._elem.tag == "testsuite":
suite = PyTestSuite(name=other.name)
suite = TestSuite(name=other.name)
for case in other:
suite._add_testcase_no_update_stats(case)
self.add_testsuite(suite)
Expand All @@ -31,7 +26,7 @@ def fromroot(cls, root_elem):
if root_elem.tag == "testsuites":
instance = cls()
elif root_elem.tag == "testsuite":
instance = PyTestSuite()
instance = TestSuite()
else:
raise JUnitXmlError("Invalid format.")
instance._elem = root_elem
Expand All @@ -54,7 +49,8 @@ def update_statistics(self):
self.time = round(time, 3)


class PyTestSuite(TestSuite):
class TestSuite(OrigTestSuite):
"""TestSuit for Pytest, with some different attributes."""
group = Attr()
id = Attr()
package = Attr()
Expand All @@ -64,16 +60,16 @@ class PyTestSuite(TestSuite):
version = Attr()

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

def __iter__(self):
return itertools.chain(
super(PyTestSuite, self).iterchildren(TestCase),
super().iterchildren(TestCase),
(
case
for suite in super(PyTestSuite, self).iterchildren(PyTestSuite)
for suite in super().iterchildren(TestSuite)
for case in suite
),
)
Expand Down Expand Up @@ -113,12 +109,108 @@ def system_err(self, value):

def testsuites(self):
"""Iterates through all testsuites."""
for suite in self.iterchildren(PyTestSuite):
for suite in self.iterchildren(TestSuite):
yield suite

def remove_testcase(self, testcase):
"""Removes a test case from the suite."""
for case in self:
if case == testcase:
super(PyTestSuite, self).remove(case)
super().remove(case)
self.update_statistics()

class StackTrace(System):
_tag = "stackTrace"

class RerunType(Result):
_tag = "rerunType"

@property
def stack_trace(self):
"""stderr."""
elem = self.child(StackTrace)
if elem is not None:
return elem.text
return None

@stack_trace.setter
def stack_trace(self, value):
trace = self.child(StackTrace)
if trace is not None:
trace.text = value
else:
trace = StackTrace(value)
self.append(trace)

@property
def system_out(self):
"""stdout."""
elem = self.child(SystemOut)
if elem is not None:
return elem.text
return None

@system_out.setter
def system_out(self, value):
out = self.child(SystemOut)
if out is not None:
out.text = value
else:
out = SystemOut(value)
self.append(out)

@property
def system_err(self):
"""stderr."""
elem = self.child(SystemErr)
if elem is not None:
return elem.text
return None

@system_err.setter
def system_err(self, value):
err = self.child(SystemErr)
if err is not None:
err.text = value
else:
err = SystemErr(value)
self.append(err)

class RerunFailure(RerunType):
_tag = "rerunFailure"

class RerunError(RerunType):
_tag = "rerunError"

class FlakyFailure(RerunType):
_tag = "flakyFailure"

class FlakyError(RerunType):
_tag = "flakyError"

class TestCase(OrigTestCase):
group = Attr()

def _rerun_results(self, _type):
elems = self.iterchildren(_type)
results = []
for elem in elems:
results.append(_type.fromelem(elem))
return results

def rerun_failures(self):
return self._rerun_results(RerunFailure)

def rerun_errors(self):
return self._rerun_results(RerunError)

def flaky_failures(self):
return self._rerun_results(FlakyFailure)

def flaky_errors(self):
return self._rerun_results(FlakyError)

def add_rerun_result(self, result):
self.append(result)


26 changes: 26 additions & 0 deletions tests/test_pytest_xml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-

import unittest
from junitparser.flavors.pytest_xml import PytestXml, TestSuite, TestCase, FlakyError, FlakyFailure, RerunError, RerunFailure
from junitparser import Failure


class Test_TestCase(unittest.TestCase):
def test_case_fromstring(self):
text = """<testcase name="testname">
<failure message="failure message" type="FailureType"/>
<rerunFailure message="Not found" type="404">
<system-out>No ha encontrado</system-out>
</rerunFailure>
<rerunFailure message="Server error" type="500">
<system-error>Error del servidor</system-error>
</rerunFailure>
<system-out>System out</system-out>
<system-err>System err</system-err>
</testcase>"""
case = TestCase.fromstring(text)
self.assertEqual(case.name, "testname")
self.assertIsInstance(case.result[0], Failure)
self.assertEqual(case.system_out, "System out")
self.assertEqual(case.system_err, "System err")
self.assertEqual(len(case.rerun_failures()), 2)

0 comments on commit da64237

Please sign in to comment.