diff --git a/mlx/unity2junit/unity2junit.py b/mlx/unity2junit/unity2junit.py index f1bbd31..7233488 100755 --- a/mlx/unity2junit/unity2junit.py +++ b/mlx/unity2junit/unity2junit.py @@ -64,6 +64,8 @@ def parse_unity_output(self): } if result.strip() == "FAIL": self.failures += 1 + if reason: + test_case["reason"] = reason.lstrip(':').strip() elif result.strip() == "SKIP": self.skipped += 1 self.test_cases.append(test_case) @@ -89,13 +91,19 @@ def generate_junit_xml(self): skipped="0" ) - ET.SubElement( + testcase_element = ET.SubElement( testsuite, "testcase", name=case["name"], classname=case["classname"], time="0.0" ) + if case["result"] == "FAIL": + message = case.get("reason", "No reason") + ET.SubElement(testcase_element, "failure", message=message) + elif case["result"] == "SKIP": + ET.SubElement(testcase_element, "skipped") + tree = ET.ElementTree(testsuites) ET.indent(tree, space=" ", level=0) tree.write(self.output_file, encoding="utf-8", xml_declaration=True) diff --git a/tests/test_in/utest_Failed_Runner.xml b/tests/test_in/utest_Failed_Runner.xml new file mode 100644 index 0000000..23caf05 --- /dev/null +++ b/tests/test_in/utest_Failed_Runner.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/unity_parsing_test.py b/tests/unity_parsing_test.py index 21c7ab6..6408e6f 100644 --- a/tests/unity_parsing_test.py +++ b/tests/unity_parsing_test.py @@ -106,6 +106,9 @@ def test_parsing_unity_log_and_building_testcases_failed(self): 'SWUTEST_INIT-TEST_INIT_I2C_READ_FAILS2', 'SWUTEST_INIT-TEST_INIT_I2C_READ_FAILS3'] expected_test_cases_Failed_Runner['result'] = ['PASS', 'PASS', 'FAIL', 'PASS', 'PASS'] + expected_test_cases_Failed_Runner['reason'] = [None, None, + 'Function Blah_SecondFunction. Called more times than ' + 'expected.', None, None] for tc in test_cases: # Find some smart way to check the test case class, name and line number @@ -113,6 +116,9 @@ def test_parsing_unity_log_and_building_testcases_failed(self): self.assertEqual(tc['line'], expected_test_cases_Failed_Runner['line'].pop(0)) self.assertEqual(tc['name'], expected_test_cases_Failed_Runner['name'].pop(0)) self.assertEqual(tc['result'], expected_test_cases_Failed_Runner['result'].pop(0)) + expected_reason = expected_test_cases_Failed_Runner['reason'].pop(0) + if expected_reason: + self.assertEqual(tc.get('reason'), expected_reason) self.assertEqual(tc['file'], 'unit_test/utest_Init.c') @@ -123,6 +129,25 @@ def test_parsing_unity_log_and_building_testcases_failed(self): self.assertEqual(converter.failures, 1) self.assertEqual(converter.skipped, 0) + def test_failed_runner_output(self): + '''Verify that utest_Failed_Runner.log is converted to utest_Failed_Runner.xml on a fixed timestamp of + 2025-09-25T13:40:24.403458+00:00 and that the failure message is correctly included.''' + fixed_timestamp_str = "2025-09-25T13:40:24.403458" + fixed_datetime = datetime.fromisoformat(fixed_timestamp_str).replace(tzinfo=timezone.utc) + expected_xml = '' + + with open(TEST_IN_DIR / 'utest_Failed_Runner.xml', 'r', encoding='utf-8') as f: + expected_xml = f.readlines() + + with tempfile.NamedTemporaryFile(mode='w+', delete=True, encoding='utf-8') as tmp_output_file: + with patch('mlx.unity2junit.unity2junit.datetime') as mock_dt: + mock_dt.now.return_value = fixed_datetime + converter = Unity2Junit(TEST_IN_DIR / 'utest_Failed_Runner.log', tmp_output_file.name) + converter.convert() + tmp_output_file.seek(0) + generated_xml = tmp_output_file.readlines() + self.assertListEqual(generated_xml, expected_xml) + def test_init_runner_output(self): '''Verify that utest_Init_Runner.log is converted to utest_Init_Runner.xml on a fixed timestamp of 2025-09-25T13:40:24.403458+00:00'''