From b4b8eb4c62c74a6c3f1b932f476e76993acf87f4 Mon Sep 17 00:00:00 2001 From: Anton Krivoborodov Date: Sun, 30 Aug 2026 09:31:13 +0000 Subject: [PATCH] fix: treat '' testcases as failed instead of passed `parse_testcase_result` only inspected the `` and `` child elements of a ``: if skipped is None and failed is None: return "passed", "" JUnit XML also uses `` for testcases that did not complete, e.g. an uncaught exception in Python's `unittest` or a crashing binary. Such a testcase has neither `` nor ``, so it fell into the branch above and was reported as `passed`. That is the worst possible failure mode for a verification report: a broken test silently shows up as a green `(passed)` badge next to the requirement it is supposed to verify. Handle `` explicitly and map it to `failed`, using the element's `message` attribute as the result text. An existing `` still takes precedence, so the reported message stays the assertion message when both elements are present. --- .../score_source_code_linker/tests/test_xml_parser.py | 11 +++++++++++ src/extensions/score_source_code_linker/xml_parser.py | 8 +++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/extensions/score_source_code_linker/tests/test_xml_parser.py b/src/extensions/score_source_code_linker/tests/test_xml_parser.py index 00c802e50..bd1d1e5e5 100644 --- a/src/extensions/score_source_code_linker/tests/test_xml_parser.py +++ b/src/extensions/score_source_code_linker/tests/test_xml_parser.py @@ -247,6 +247,17 @@ def test_parse_testcase_result(): ET.SubElement(tc4, "skipped", {"message": "skp"}) assert xml_parser.parse_testcase_result(tc4) == ("skipped", "skp") + # An '' (e.g. uncaught exception) must not be reported as 'passed'. + tc5 = ET.Element("testcase", {"name": "e"}) + ET.SubElement(tc5, "error", {"message": "boom"}) + assert xml_parser.parse_testcase_result(tc5) == ("failed", "boom") + + # A '' takes precedence over an additional ''. + tc6 = ET.Element("testcase", {"name": "f"}) + ET.SubElement(tc6, "failure", {"message": "err"}) + ET.SubElement(tc6, "error", {"message": "boom"}) + assert xml_parser.parse_testcase_result(tc6) == ("failed", "err") + @add_test_properties( partially_verifies=["tool_req__docs_test_link_testcase"], diff --git a/src/extensions/score_source_code_linker/xml_parser.py b/src/extensions/score_source_code_linker/xml_parser.py index 131014889..97a5bc044 100644 --- a/src/extensions/score_source_code_linker/xml_parser.py +++ b/src/extensions/score_source_code_linker/xml_parser.py @@ -169,14 +169,20 @@ def parse_testcase_result(testcase: ET.Element) -> tuple[str, str]: """ skipped = testcase.find("skipped") failed = testcase.find("failure") + # An '' means the testcase did not complete, e.g. an uncaught + # exception in Python's unittest or a crashing binary. It must not be + # reported as 'passed', so it is treated like a failure. + errored = testcase.find("error") status = testcase.get("status") # NOTE: Special CPP case of 'disabled' if status is not None and status == "notrun": return "disabled", "" - if skipped is None and failed is None: + if skipped is None and failed is None and errored is None: return "passed", "" if failed is not None: return "failed", failed.get("message", "") + if errored is not None: + return "failed", errored.get("message", "") if skipped is not None: return "skipped", skipped.get("message", "") # TODO: Test all possible permuations of this to find if this is unreachable