From 7f341ac2ed186e9b3cf936fbe6bb726ab8210f41 Mon Sep 17 00:00:00 2001 From: Kurt Godwin Date: Wed, 7 Sep 2022 11:33:43 -0400 Subject: [PATCH 1/9] Add user_properties to test case report --- pytest_nunit/plugin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pytest_nunit/plugin.py b/pytest_nunit/plugin.py index fd9e796..f7852d4 100644 --- a/pytest_nunit/plugin.py +++ b/pytest_nunit/plugin.py @@ -165,6 +165,7 @@ def record_testreport(self, testreport): r["call-report"] = testreport r["error"] = 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() @@ -390,7 +391,7 @@ def pytest_sessionfinish(self, session, *args): full_report = self._create_module_report(self.cases) self.stats.update(full_report.stats) - # pytest-xdist collection is done on workers, + # 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(): From 4439e56a842cb61820a90a83418b6f01ec0732c6 Mon Sep 17 00:00:00 2001 From: Kurt Godwin Date: Fri, 6 Jan 2023 16:38:12 -0500 Subject: [PATCH 2/9] convert objects to text before translating ampersand --- pytest_nunit/attrs2xml.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytest_nunit/attrs2xml.py b/pytest_nunit/attrs2xml.py index 9271e81..45cca85 100644 --- a/pytest_nunit/attrs2xml.py +++ b/pytest_nunit/attrs2xml.py @@ -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': ""}) From d05421620eaa69b5cce2e03f0e414752dac49540 Mon Sep 17 00:00:00 2001 From: Kurt Godwin Date: Fri, 24 Mar 2023 13:54:26 -0400 Subject: [PATCH 3/9] don't log in __init__ and filter output --- pytest_nunit/plugin.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pytest_nunit/plugin.py b/pytest_nunit/plugin.py index f7852d4..0350c4f 100644 --- a/pytest_nunit/plugin.py +++ b/pytest_nunit/plugin.py @@ -18,6 +18,7 @@ import logging import pytest +import string log = logging.getLogger(__name__) @@ -120,6 +121,8 @@ def pytest_unconfigure(config): del config._nunitxml config.pluginmanager.unregister(nunitxml) +def filter_ctrl(str): + return "".join(filter(lambda x: x in string.printable, str)) class _NunitNodeReporter: def __init__(self, nodeid, nunit_xml): @@ -163,7 +166,7 @@ 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": @@ -269,7 +272,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 From 86fa73f47bf643c1cebe7eafe08eefbf5d6ceada Mon Sep 17 00:00:00 2001 From: Kurt Godwin Date: Thu, 30 Mar 2023 09:56:41 -0400 Subject: [PATCH 4/9] Filter cdata --- pytest_nunit/nunit.py | 19 ++++++++++++++----- pytest_nunit/plugin.py | 5 +---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/pytest_nunit/nunit.py b/pytest_nunit/nunit.py index 1aea7ef..969a1db 100644 --- a/pytest_nunit/nunit.py +++ b/pytest_nunit/nunit.py @@ -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 @@ -34,6 +35,14 @@ } +def filter_ctrl(str): + return "".join(filter(lambda x: x in string.printable, str)) + +class CDataComment_filtered(CdataComment): + def __init__(self, text): + text = filter_ctrl(text) + super().__init__(text) + def _get_user_id(): try: username = getpass.getuser() @@ -62,7 +71,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`` @@ -171,11 +180,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], diff --git a/pytest_nunit/plugin.py b/pytest_nunit/plugin.py index 0350c4f..c2fc9b2 100644 --- a/pytest_nunit/plugin.py +++ b/pytest_nunit/plugin.py @@ -14,7 +14,7 @@ import functools from collections import namedtuple, defaultdict, Counter -from .nunit import NunitTestRun +from .nunit import NunitTestRun, filter_ctrl import logging import pytest @@ -121,9 +121,6 @@ def pytest_unconfigure(config): del config._nunitxml config.pluginmanager.unregister(nunitxml) -def filter_ctrl(str): - return "".join(filter(lambda x: x in string.printable, str)) - class _NunitNodeReporter: def __init__(self, nodeid, nunit_xml): self.id = nodeid From 5ce9f13083b056e56cf9da31fb799e0312826ecf Mon Sep 17 00:00:00 2001 From: Kurt Godwin Date: Tue, 25 Apr 2023 08:33:01 -0400 Subject: [PATCH 5/9] Remove cwd from reports --- pytest_nunit/nunit.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pytest_nunit/nunit.py b/pytest_nunit/nunit.py index 969a1db..39072f7 100644 --- a/pytest_nunit/nunit.py +++ b/pytest_nunit/nunit.py @@ -36,7 +36,11 @@ def filter_ctrl(str): - return "".join(filter(lambda x: x in string.printable, str)) + if str: + printable = "".join(filter(lambda x: x in string.printable, str)) + cwd = os.path.curdir + str.replace(cwd, "") + return str class CDataComment_filtered(CdataComment): def __init__(self, text): From 574b480986e1f9754d4467a779545e206b613df3 Mon Sep 17 00:00:00 2001 From: Kurt Godwin Date: Wed, 26 Apr 2023 08:42:00 -0400 Subject: [PATCH 6/9] only remove path from tests --- pytest_nunit/nunit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest_nunit/nunit.py b/pytest_nunit/nunit.py index 39072f7..0a7aa0d 100644 --- a/pytest_nunit/nunit.py +++ b/pytest_nunit/nunit.py @@ -39,7 +39,7 @@ def filter_ctrl(str): if str: printable = "".join(filter(lambda x: x in string.printable, str)) cwd = os.path.curdir - str.replace(cwd, "") + str.replace(os.path.join(cwd, "tests"), "tests") return str class CDataComment_filtered(CdataComment): From e5580dd4d8115c0a023bd380c7d48f99ba2240cf Mon Sep 17 00:00:00 2001 From: Kurt Godwin Date: Wed, 26 Apr 2023 15:30:13 -0400 Subject: [PATCH 7/9] fixed filter --- pytest_nunit/nunit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytest_nunit/nunit.py b/pytest_nunit/nunit.py index 0a7aa0d..254afb0 100644 --- a/pytest_nunit/nunit.py +++ b/pytest_nunit/nunit.py @@ -37,9 +37,9 @@ def filter_ctrl(str): if str: - printable = "".join(filter(lambda x: x in string.printable, str)) + str = "".join(filter(lambda x: x in string.printable, str)) cwd = os.path.curdir - str.replace(os.path.join(cwd, "tests"), "tests") + str = str.replace(os.path.join(cwd, "tests"), "tests") return str class CDataComment_filtered(CdataComment): From e03f7aeacda4501cee1bfd116cd8b08165848a84 Mon Sep 17 00:00:00 2001 From: Kurt Godwin Date: Fri, 28 Apr 2023 07:21:18 -0400 Subject: [PATCH 8/9] set reson if not present --- pytest_nunit/nunit.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pytest_nunit/nunit.py b/pytest_nunit/nunit.py index 254afb0..77623a3 100644 --- a/pytest_nunit/nunit.py +++ b/pytest_nunit/nunit.py @@ -169,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"]), From c45be8c392343f3c7c1a9ab4228f6b82a4c8b3a7 Mon Sep 17 00:00:00 2001 From: Kurt Godwin Date: Mon, 1 May 2023 14:57:59 -0400 Subject: [PATCH 9/9] catch exceptions in xml report generator --- pytest_nunit/plugin.py | 53 +++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/pytest_nunit/plugin.py b/pytest_nunit/plugin.py index c2fc9b2..1f3753c 100644 --- a/pytest_nunit/plugin.py +++ b/pytest_nunit/plugin.py @@ -388,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."""