diff --git a/unity_test_parser.py b/unity_test_parser.py new file mode 100644 index 0000000..5c4f64e --- /dev/null +++ b/unity_test_parser.py @@ -0,0 +1,98 @@ +import argparse +import xml.etree.ElementTree as ET +from termcolor import colored + + +def parse_args(): + parser = argparse.ArgumentParser(description='Parse Unity test results XML files and display test results.') + parser.add_argument('editmode_xml_file', type=str, help='Path to Unity EditMode test results XML file') + parser.add_argument('playmode_xml_file', type=str, help='Path to Unity PlayMode test results XML file') + return parser.parse_args() + + +def get_test_suites(xml_file, mode): + tree = ET.parse(xml_file) + root = tree.getroot() + + test_suites = [] + # get all test_suite elements with type assembly + for test_suite in root.iter('test-suite'): + if test_suite.attrib['type'] == 'Assembly': + test_suites.append(test_suite) + + return test_suites + +def get_tests_cases(test_suite): + test_cases = [] + for test_case in test_suite.iter('test-case'): + test_cases.append({ + 'name': test_case.attrib['name'], + 'classname': test_case.attrib['classname'], + 'result': test_case.attrib['result'], + 'duration': test_case.attrib['duration'], + }) + return test_cases + + +def print_test_results(test_suites, mode): + print(f'\n================ {mode} Tests ================') + all_tests = [] + for test_suite in test_suites: + test_suite_name = test_suite.attrib['name'] + print("\n" + colored(test_suite_name, 'cyan')) + + tests = get_tests_cases(test_suite) + all_tests += tests + if tests: + passed_tests = [] + failed_tests = [] + for test in tests: + test_name = test['name'] + test_classname = test['classname'] + test_result = test['result'] + test_duration = test['duration'] + test_duration_str = '{:.3f}s'.format(float(test_duration)) + if test_result == 'Passed': + print(colored('✓ PASS', 'green'), test_name, '({} {})'.format(test_classname, test_duration_str)) + passed_tests.append(test) + elif test_result == 'Failed': + print(colored('✗ FAIL', 'red'), test_name, '({} {})'.format(test_classname, test_duration_str)) + failed_tests.append(test) + else: + print(colored('⚠ SKIP', 'yellow'), test_name, '({} {})'.format(test_classname, test_duration_str)) + return all_tests + +def get_combined_results(edit_results, play_results): + combined_results = edit_results + play_results + return combined_results + +def print_summary(combined_results): + passed_tests = [] + failed_tests = [] + for test in combined_results: + test_result = test['result'] + if test_result == 'Passed': + passed_tests.append(test) + elif test_result == 'Failed': + failed_tests.append(test) + + print('\n=================== Summary ===================') + print(colored('✓ Passed tests', 'green') + ': {} / {}'.format(len(passed_tests), len(combined_results))) + print(colored('✗ Failed tests', 'red') + ': {} / {}\n'.format(len(failed_tests), len(combined_results))) + + if len(failed_tests) > 0: + # exit with error + exit(1) + +if __name__ == '__main__': + args = parse_args() + + edit_suites = get_test_suites(args.editmode_xml_file, 'EditMode') + play_suites = get_test_suites(args.playmode_xml_file, 'PlayMode') + + edit_tests = print_test_results(edit_suites, 'EditMode') + play_tests = print_test_results(play_suites, 'PlayMode') + + combined_results = get_combined_results(edit_tests, play_tests) + print_summary(combined_results) +