diff --git a/mlx/unity2junit/unity2junit.py b/mlx/unity2junit/unity2junit.py index 87dccd5..ae3b418 100755 --- a/mlx/unity2junit/unity2junit.py +++ b/mlx/unity2junit/unity2junit.py @@ -14,7 +14,7 @@ class Unity2Junit: """Converts a Unity test output log to a JUnit XML report.""" - def __init__(self, log_file, output_file): + def __init__(self, log_file, output_file, tc_prefix=None): self.log_file = log_file self.output_file = output_file self.test_cases = [] @@ -22,6 +22,7 @@ def __init__(self, log_file, output_file): self.total_tests = 0 self.failures = 0 self.skipped = 0 + self.test_case_prefix = tc_prefix def parse_unity_output(self): """Parses the Unity log file and populates test case data.""" @@ -36,8 +37,11 @@ def parse_unity_output(self): filename = os.path.basename(file_path).replace("utest_", "").split('.')[0].upper() self.default_suite_name = filename # Set the default testsuite name + if self.test_case_prefix is None: + self.test_case_prefix = f"SWUTEST_{filename}-" + # Modify the test name: replace the underscore between SWUTEST_ and the next part with a hyphen - formatted_test_name = f"SWUTEST_{filename}-{test_name.upper()}" + formatted_test_name = f"{self.test_case_prefix}{test_name.upper()}" test_case = { "name": formatted_test_name, @@ -97,9 +101,10 @@ def main(): parser.add_argument("log_file", help="Path to the Unity test output log file.") parser.add_argument("output_file", help="Path to the output JUnit XML file.") parser.add_argument("--version", "-v", action="version", version=f"%(prog)s {__version__}") + parser.add_argument("--tc-prefix", help="Prefix to add to each test case name.", default=None) args = parser.parse_args() - converter = Unity2Junit(args.log_file, args.output_file) + converter = Unity2Junit(args.log_file, args.output_file, tc_prefix=args.tc_prefix) converter.convert() diff --git a/tests/unity_parsing_test.py b/tests/unity_parsing_test.py index 70ff21b..04f7dd8 100644 --- a/tests/unity_parsing_test.py +++ b/tests/unity_parsing_test.py @@ -142,6 +142,127 @@ def test_init_runner_output(self): generated_xml = tmp_output_file.readlines() self.assertListEqual(generated_xml, expected_xml) + def test_force_test_case_prefix(self): + ''' Verify that when a prefix is forced, it is used as the testsuite name.''' + with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_output_file: + converter = Unity2Junit(TEST_IN_DIR / 'utest_Init_Runner.log', tmp_output_file.name, + tc_prefix="FORCED_PREFIX-") + converter.parse_unity_output() + test_cases = converter.test_cases + + expected_test_cases_Init_Runner = {} + expected_test_cases_Init_Runner['classname'] = [ + 'INIT.FORCED_PREFIX-TEST_INIT_SUCCESS', 'INIT.FORCED_PREFIX-TEST_INIT_WRONG_EEPROM_VERSION', + 'INIT.FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS', 'INIT.FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS2', + 'INIT.FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS3'] + expected_test_cases_Init_Runner['line'] = ['49', '124', '135', '145', '163'] + expected_test_cases_Init_Runner['name'] = ['FORCED_PREFIX-TEST_INIT_SUCCESS', + 'FORCED_PREFIX-TEST_INIT_WRONG_EEPROM_VERSION', + 'FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS', + 'FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS2', + 'FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS3'] + + for tc in test_cases: + # Find some smart way to check the test case class, name and line number + self.assertEqual(tc['classname'], expected_test_cases_Init_Runner['classname'].pop(0)) + self.assertEqual(tc['line'], expected_test_cases_Init_Runner['line'].pop(0)) + self.assertEqual(tc['name'], expected_test_cases_Init_Runner['name'].pop(0)) + self.assertEqual(tc['result'], 'PASS') + + self.assertEqual(tc['file'], 'unit_test/utest_Init.c') + self.assertEqual(tc['suite'], 'INIT') # The suite in test cases remains the same + + def test_force_test_case_prefix_noname(self): + ''' Verify that when a prefix is forced, it is used as the testsuite name even when utest.c is used.''' + with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_output_file: + converter = Unity2Junit(TEST_IN_DIR / 'utest_Noname_Runner.log', tmp_output_file.name, + tc_prefix="FORCED_PREFIX-") + converter.parse_unity_output() + test_cases = converter.test_cases + + expected_test_cases_Noname_Runner = {} + expected_test_cases_Noname_Runner['classname'] = [ + 'UTEST.FORCED_PREFIX-TEST_INIT_SUCCESS', 'UTEST.FORCED_PREFIX-TEST_INIT_WRONG_EEPROM_VERSION', + 'UTEST.FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS', 'UTEST.FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS2', + 'UTEST.FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS3'] + expected_test_cases_Noname_Runner['line'] = ['49', '124', '135', '145', '163'] + expected_test_cases_Noname_Runner['name'] = ['FORCED_PREFIX-TEST_INIT_SUCCESS', + 'FORCED_PREFIX-TEST_INIT_WRONG_EEPROM_VERSION', + 'FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS', + 'FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS2', + 'FORCED_PREFIX-TEST_INIT_I2C_READ_FAILS3'] + + for tc in test_cases: + # Find some smart way to check the test case class, name and line number + self.assertEqual(tc['classname'], expected_test_cases_Noname_Runner['classname'].pop(0)) + self.assertEqual(tc['line'], expected_test_cases_Noname_Runner['line'].pop(0)) + self.assertEqual(tc['name'], expected_test_cases_Noname_Runner['name'].pop(0)) + self.assertEqual(tc['result'], 'PASS') + + self.assertEqual(tc['file'], 'unit_test/utest.c') + self.assertEqual(tc['suite'], 'UTEST') # The suite in test cases remains the same + + def test_force_test_case_prefix_empty(self): + ''' Verify that when an empty prefix is forced, the default prefix is used as the testsuite name.''' + with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_output_file: + converter = Unity2Junit(TEST_IN_DIR / 'utest_Init_Runner.log', tmp_output_file.name, + tc_prefix="") + converter.parse_unity_output() + test_cases = converter.test_cases + + expected_test_cases_Init_Runner = {} + expected_test_cases_Init_Runner['classname'] = [ + 'INIT.TEST_INIT_SUCCESS', 'INIT.TEST_INIT_WRONG_EEPROM_VERSION', + 'INIT.TEST_INIT_I2C_READ_FAILS', 'INIT.TEST_INIT_I2C_READ_FAILS2', + 'INIT.TEST_INIT_I2C_READ_FAILS3'] + expected_test_cases_Init_Runner['line'] = ['49', '124', '135', '145', '163'] + expected_test_cases_Init_Runner['name'] = ['TEST_INIT_SUCCESS', + 'TEST_INIT_WRONG_EEPROM_VERSION', + 'TEST_INIT_I2C_READ_FAILS', + 'TEST_INIT_I2C_READ_FAILS2', + 'TEST_INIT_I2C_READ_FAILS3'] + + for tc in test_cases: + # Find some smart way to check the test case class, name and line number + self.assertEqual(tc['classname'], expected_test_cases_Init_Runner['classname'].pop(0)) + self.assertEqual(tc['line'], expected_test_cases_Init_Runner['line'].pop(0)) + self.assertEqual(tc['name'], expected_test_cases_Init_Runner['name'].pop(0)) + self.assertEqual(tc['result'], 'PASS') + + self.assertEqual(tc['file'], 'unit_test/utest_Init.c') + self.assertEqual(tc['suite'], 'INIT') # The suite in test cases remains the same + + def test_force_test_case_prefix_empty_noname(self): + ''' Verify that when an empty prefix is forced, the default prefix is used as the testsuite name even when + utest.c is used.''' + with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_output_file: + converter = Unity2Junit(TEST_IN_DIR / 'utest_Noname_Runner.log', tmp_output_file.name, + tc_prefix="") + converter.parse_unity_output() + test_cases = converter.test_cases + + expected_test_cases_Noname_Runner = {} + expected_test_cases_Noname_Runner['classname'] = [ + 'UTEST.TEST_INIT_SUCCESS', 'UTEST.TEST_INIT_WRONG_EEPROM_VERSION', + 'UTEST.TEST_INIT_I2C_READ_FAILS', 'UTEST.TEST_INIT_I2C_READ_FAILS2', + 'UTEST.TEST_INIT_I2C_READ_FAILS3'] + expected_test_cases_Noname_Runner['line'] = ['49', '124', '135', '145', '163'] + expected_test_cases_Noname_Runner['name'] = ['TEST_INIT_SUCCESS', + 'TEST_INIT_WRONG_EEPROM_VERSION', + 'TEST_INIT_I2C_READ_FAILS', + 'TEST_INIT_I2C_READ_FAILS2', + 'TEST_INIT_I2C_READ_FAILS3'] + + for tc in test_cases: + # Find some smart way to check the test case class, name and line number + self.assertEqual(tc['classname'], expected_test_cases_Noname_Runner['classname'].pop(0)) + self.assertEqual(tc['line'], expected_test_cases_Noname_Runner['line'].pop(0)) + self.assertEqual(tc['name'], expected_test_cases_Noname_Runner['name'].pop(0)) + self.assertEqual(tc['result'], 'PASS') + + self.assertEqual(tc['file'], 'unit_test/utest.c') + self.assertEqual(tc['suite'], 'UTEST') # The suite in test cases remains the same + if __name__ == '__main__': unittest.main()