Skip to content
Open
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions pytest_nunit/attrs2xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
class CdataComment(ET.Element):
def __init__(self, text):
super(CdataComment, self).__init__("CDATA!")
if type(text) is not str:
text = str(text)
self.text = escape(text, {'\x1b': ""})


Expand Down
27 changes: 22 additions & 5 deletions pytest_nunit/nunit.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
ValueMatchFilterType,
)
from .attrs2xml import AttrsXmlRenderer, CdataComment
import string

FRAMEWORK_VERSION = "3.6.2" # Nunit version this was based on
CLR_VERSION = sys.version
Expand All @@ -34,6 +35,18 @@
}


def filter_ctrl(str):
if str:
str = "".join(filter(lambda x: x in string.printable, str))
cwd = os.path.curdir
str = str.replace(os.path.join(cwd, "tests"), "tests")
return str

class CDataComment_filtered(CdataComment):
def __init__(self, text):
text = filter_ctrl(text)
super().__init__(text)

def _get_user_id():
try:
username = getpass.getuser()
Expand Down Expand Up @@ -62,7 +75,7 @@ def _format_attachments(case, attach_on):

:param case: The test case
:type case: :class:`pytest.TestCase`

:param attach_on: Attach-on criteria, one of any|pass|fail
:type attach_on: ``str``

Expand Down Expand Up @@ -156,6 +169,10 @@ def environment(self):
)

def test_cases(self, module):
for nodeid, case in self.nunitxml.modules[module].cases.items():
if "reason" not in case:
case['reason'] = 'Not set'

return [
TestCaseElementType(
id_=str(case["idref"]),
Expand All @@ -171,11 +188,11 @@ def test_cases(self, module):
environment=self.environment,
settings=None, # TODO : Add settings as optional fixture
failure=FailureType(
message=CdataComment(text=case["error"]),
stack_trace=CdataComment(text=case["stack-trace"]),
message=CDataComment_filtered(text=case["error"]),
stack_trace=CDataComment_filtered(text=case["stack-trace"]),
),
reason=ReasonType(message=CdataComment(text=case["reason"])),
output=CdataComment(text=case["reason"]),
reason=ReasonType(message=CDataComment_filtered(text=case["reason"])),
output=CDataComment_filtered(text=filter_ctrl(case["reason"])),
assertions=_format_assertions(case),
attachments=_format_attachments(case, self.nunitxml.attach_on),
classname=get_node_names(nodeid)[0],
Expand Down
62 changes: 34 additions & 28 deletions pytest_nunit/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
import functools
from collections import namedtuple, defaultdict, Counter

from .nunit import NunitTestRun
from .nunit import NunitTestRun, filter_ctrl

import logging
import pytest
import string

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -120,7 +121,6 @@ def pytest_unconfigure(config):
del config._nunitxml
config.pluginmanager.unregister(nunitxml)


class _NunitNodeReporter:
def __init__(self, nodeid, nunit_xml):
self.id = nodeid
Expand Down Expand Up @@ -163,8 +163,9 @@ def record_testreport(self, testreport):
elif testreport.when == "call":
r = self.nunit_xml.cases[testreport.nodeid]
r["call-report"] = testreport
r["error"] = testreport.longreprtext
r["error"] = filter_ctrl(testreport.longreprtext)
r["stack-trace"] = self.nunit_xml._getcrashline(testreport)
r["properties"].update(testreport.user_properties)
elif testreport.when == "teardown":
r = self.nunit_xml.cases[testreport.nodeid]
r["stop"] = datetime.utcnow()
Expand Down Expand Up @@ -268,7 +269,7 @@ def __init__(
self.show_username = show_username
self.show_user_domain = show_user_domain
self.attach_on = attach_on
logging.debug("Attach on criteria : {0}".format(attach_on))
#logging.debug("Attach on criteria : {0}".format(attach_on))
self.idrefindex = 100 # Create a unique ID counter
self.filters = filters

Expand Down Expand Up @@ -387,30 +388,35 @@ def pytest_sessionfinish(self, session, *args):
self.suite_stop_time - self.suite_start_time
).total_seconds()

full_report = self._create_module_report(self.cases)
self.stats.update(full_report.stats)

# pytest-xdist collection is done on workers,
# so node_to_module_map is empty
if not self.node_to_module_map and self.cases:
for case_name, case in self.cases.items():
if 'path' in case:
self.node_to_module_map[case_name] = case['path']
else:
self.node_to_module_map[case_name] = ParentlessNode

# Sort nodes into modules
for module_id in set(self.node_to_module_map.values()):
cases = {
nodeid: self.cases[nodeid]
for nodeid, m_id in self.node_to_module_map.items()
if module_id == m_id and nodeid in self.cases
}
self.modules[module_id] = self._create_module_report(cases)

with open(self.logfile, "w", encoding="utf-8") as logfile:
result = NunitTestRun(self).generate_xml()
logfile.write(result.decode(encoding="utf-8"))
try:
full_report = self._create_module_report(self.cases)
self.stats.update(full_report.stats)

# pytest-xdist collection is done on workers,
# so node_to_module_map is empty
if not self.node_to_module_map and self.cases:
for case_name, case in self.cases.items():
if 'path' in case:
self.node_to_module_map[case_name] = case['path']
else:
self.node_to_module_map[case_name] = ParentlessNode

# Sort nodes into modules
for module_id in set(self.node_to_module_map.values()):
cases = {
nodeid: self.cases[nodeid]
for nodeid, m_id in self.node_to_module_map.items()
if module_id == m_id and nodeid in self.cases
}
self.modules[module_id] = self._create_module_report(cases)

with open(self.logfile, "w", encoding="utf-8") as logfile:
result = NunitTestRun(self).generate_xml()
logfile.write(result.decode(encoding="utf-8"))

except BaseException:
# ignore errors from the report generation as it is buggy
pass

def pytest_terminal_summary(self, terminalreporter):
"""Notify XML report path."""
Expand Down