19750e409Sopenharmony_ciimport sys 29750e409Sopenharmony_ciimport os 39750e409Sopenharmony_cifrom glob import glob 49750e409Sopenharmony_ci 59750e409Sopenharmony_cifrom pyparsing import * 69750e409Sopenharmony_cifrom junit_xml import TestSuite, TestCase 79750e409Sopenharmony_ci 89750e409Sopenharmony_ci 99750e409Sopenharmony_ciclass UnityTestSummary: 109750e409Sopenharmony_ci def __init__(self): 119750e409Sopenharmony_ci self.report = '' 129750e409Sopenharmony_ci self.total_tests = 0 139750e409Sopenharmony_ci self.failures = 0 149750e409Sopenharmony_ci self.ignored = 0 159750e409Sopenharmony_ci self.targets = 0 169750e409Sopenharmony_ci self.root = None 179750e409Sopenharmony_ci self.test_suites = dict() 189750e409Sopenharmony_ci 199750e409Sopenharmony_ci def run(self): 209750e409Sopenharmony_ci # Clean up result file names 219750e409Sopenharmony_ci results = [] 229750e409Sopenharmony_ci for target in self.targets: 239750e409Sopenharmony_ci results.append(target.replace('\\', '/')) 249750e409Sopenharmony_ci 259750e409Sopenharmony_ci # Dig through each result file, looking for details on pass/fail: 269750e409Sopenharmony_ci for result_file in results: 279750e409Sopenharmony_ci lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n'))) 289750e409Sopenharmony_ci if len(lines) == 0: 299750e409Sopenharmony_ci raise Exception("Empty test result file: %s" % result_file) 309750e409Sopenharmony_ci 319750e409Sopenharmony_ci # define an expression for your file reference 329750e409Sopenharmony_ci entry_one = Combine( 339750e409Sopenharmony_ci oneOf(list(alphas)) + ':/' + 349750e409Sopenharmony_ci Word(alphanums + '_-./')) 359750e409Sopenharmony_ci 369750e409Sopenharmony_ci entry_two = Word(printables + ' ', excludeChars=':') 379750e409Sopenharmony_ci entry = entry_one | entry_two 389750e409Sopenharmony_ci 399750e409Sopenharmony_ci delimiter = Literal(':').suppress() 409750e409Sopenharmony_ci tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName( 419750e409Sopenharmony_ci 'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName( 429750e409Sopenharmony_ci 'tc_status') + Optional( 439750e409Sopenharmony_ci delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line") 449750e409Sopenharmony_ci 459750e409Sopenharmony_ci eol = LineEnd().suppress() 469750e409Sopenharmony_ci sol = LineStart().suppress() 479750e409Sopenharmony_ci blank_line = sol + eol 489750e409Sopenharmony_ci 499750e409Sopenharmony_ci tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName( 509750e409Sopenharmony_ci "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName( 519750e409Sopenharmony_ci "tc_summary") 529750e409Sopenharmony_ci tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result") 539750e409Sopenharmony_ci 549750e409Sopenharmony_ci # run it and see... 559750e409Sopenharmony_ci pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line) 569750e409Sopenharmony_ci pp1.ignore(blank_line | OneOrMore("-")) 579750e409Sopenharmony_ci 589750e409Sopenharmony_ci result = list() 599750e409Sopenharmony_ci for l in lines: 609750e409Sopenharmony_ci result.append((pp1.parseString(l)).asDict()) 619750e409Sopenharmony_ci # delete empty results 629750e409Sopenharmony_ci result = filter(None, result) 639750e409Sopenharmony_ci 649750e409Sopenharmony_ci tc_list = list() 659750e409Sopenharmony_ci for r in result: 669750e409Sopenharmony_ci if 'tc_line' in r: 679750e409Sopenharmony_ci tmp_tc_line = r['tc_line'] 689750e409Sopenharmony_ci 699750e409Sopenharmony_ci # get only the file name which will be used as the classname 709750e409Sopenharmony_ci file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0] 719750e409Sopenharmony_ci tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name) 729750e409Sopenharmony_ci if 'tc_status' in tmp_tc_line: 739750e409Sopenharmony_ci if str(tmp_tc_line['tc_status']) == 'IGNORE': 749750e409Sopenharmony_ci if 'tc_msg' in tmp_tc_line: 759750e409Sopenharmony_ci tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'], 769750e409Sopenharmony_ci output=r'[File]={0}, [Line]={1}'.format( 779750e409Sopenharmony_ci tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) 789750e409Sopenharmony_ci else: 799750e409Sopenharmony_ci tmp_tc.add_skipped_info(message=" ") 809750e409Sopenharmony_ci elif str(tmp_tc_line['tc_status']) == 'FAIL': 819750e409Sopenharmony_ci if 'tc_msg' in tmp_tc_line: 829750e409Sopenharmony_ci tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'], 839750e409Sopenharmony_ci output=r'[File]={0}, [Line]={1}'.format( 849750e409Sopenharmony_ci tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) 859750e409Sopenharmony_ci else: 869750e409Sopenharmony_ci tmp_tc.add_failure_info(message=" ") 879750e409Sopenharmony_ci 889750e409Sopenharmony_ci tc_list.append((str(result_file), tmp_tc)) 899750e409Sopenharmony_ci 909750e409Sopenharmony_ci for k, v in tc_list: 919750e409Sopenharmony_ci try: 929750e409Sopenharmony_ci self.test_suites[k].append(v) 939750e409Sopenharmony_ci except KeyError: 949750e409Sopenharmony_ci self.test_suites[k] = [v] 959750e409Sopenharmony_ci ts = [] 969750e409Sopenharmony_ci for suite_name in self.test_suites: 979750e409Sopenharmony_ci ts.append(TestSuite(suite_name, self.test_suites[suite_name])) 989750e409Sopenharmony_ci 999750e409Sopenharmony_ci with open('result.xml', 'w') as f: 1009750e409Sopenharmony_ci TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8') 1019750e409Sopenharmony_ci 1029750e409Sopenharmony_ci return self.report 1039750e409Sopenharmony_ci 1049750e409Sopenharmony_ci def set_targets(self, target_array): 1059750e409Sopenharmony_ci self.targets = target_array 1069750e409Sopenharmony_ci 1079750e409Sopenharmony_ci def set_root_path(self, path): 1089750e409Sopenharmony_ci self.root = path 1099750e409Sopenharmony_ci 1109750e409Sopenharmony_ci @staticmethod 1119750e409Sopenharmony_ci def usage(err_msg=None): 1129750e409Sopenharmony_ci print("\nERROR: ") 1139750e409Sopenharmony_ci if err_msg: 1149750e409Sopenharmony_ci print(err_msg) 1159750e409Sopenharmony_ci print("\nUsage: unity_test_summary.py result_file_directory/ root_path/") 1169750e409Sopenharmony_ci print(" result_file_directory - The location of your results files.") 1179750e409Sopenharmony_ci print(" Defaults to current directory if not specified.") 1189750e409Sopenharmony_ci print(" Should end in / if specified.") 1199750e409Sopenharmony_ci print(" root_path - Helpful for producing more verbose output if using relative paths.") 1209750e409Sopenharmony_ci sys.exit(1) 1219750e409Sopenharmony_ci 1229750e409Sopenharmony_ci 1239750e409Sopenharmony_ciif __name__ == '__main__': 1249750e409Sopenharmony_ci uts = UnityTestSummary() 1259750e409Sopenharmony_ci try: 1269750e409Sopenharmony_ci # look in the specified or current directory for result files 1279750e409Sopenharmony_ci if len(sys.argv) > 1: 1289750e409Sopenharmony_ci targets_dir = sys.argv[1] 1299750e409Sopenharmony_ci else: 1309750e409Sopenharmony_ci targets_dir = './' 1319750e409Sopenharmony_ci targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*'))) 1329750e409Sopenharmony_ci if len(targets) == 0: 1339750e409Sopenharmony_ci raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir) 1349750e409Sopenharmony_ci uts.set_targets(targets) 1359750e409Sopenharmony_ci 1369750e409Sopenharmony_ci # set the root path 1379750e409Sopenharmony_ci if len(sys.argv) > 2: 1389750e409Sopenharmony_ci root_path = sys.argv[2] 1399750e409Sopenharmony_ci else: 1409750e409Sopenharmony_ci root_path = os.path.split(__file__)[0] 1419750e409Sopenharmony_ci uts.set_root_path(root_path) 1429750e409Sopenharmony_ci 1439750e409Sopenharmony_ci # run the summarizer 1449750e409Sopenharmony_ci print(uts.run()) 1459750e409Sopenharmony_ci except Exception as e: 1469750e409Sopenharmony_ci UnityTestSummary.usage(e) 147