135375f98Sopenharmony_ci#! python3 235375f98Sopenharmony_ci# ========================================== 335375f98Sopenharmony_ci# Fork from Unity Project - A Test Framework for C 435375f98Sopenharmony_ci# Pull request on Gerrit in progress, the objective of this file is to be deleted when official Unity deliveries 535375f98Sopenharmony_ci# include that modification 635375f98Sopenharmony_ci# Copyright (c) 2015 Alexander Mueller / XelaRellum@web.de 735375f98Sopenharmony_ci# [Released under MIT License. Please refer to license.txt for details] 835375f98Sopenharmony_ci# ========================================== 935375f98Sopenharmony_ciimport sys 1035375f98Sopenharmony_ciimport os 1135375f98Sopenharmony_cifrom glob import glob 1235375f98Sopenharmony_ciimport argparse 1335375f98Sopenharmony_ci 1435375f98Sopenharmony_cifrom pyparsing import * 1535375f98Sopenharmony_cifrom junit_xml import TestSuite, TestCase 1635375f98Sopenharmony_ci 1735375f98Sopenharmony_ci 1835375f98Sopenharmony_ciclass UnityTestSummary: 1935375f98Sopenharmony_ci def __init__(self): 2035375f98Sopenharmony_ci self.report = '' 2135375f98Sopenharmony_ci self.total_tests = 0 2235375f98Sopenharmony_ci self.failures = 0 2335375f98Sopenharmony_ci self.ignored = 0 2435375f98Sopenharmony_ci self.targets = 0 2535375f98Sopenharmony_ci self.root = None 2635375f98Sopenharmony_ci self.output = None 2735375f98Sopenharmony_ci self.test_suites = dict() 2835375f98Sopenharmony_ci 2935375f98Sopenharmony_ci def run(self): 3035375f98Sopenharmony_ci # Clean up result file names 3135375f98Sopenharmony_ci results = [] 3235375f98Sopenharmony_ci for target in self.targets: 3335375f98Sopenharmony_ci results.append(target.replace('\\', '/')) 3435375f98Sopenharmony_ci 3535375f98Sopenharmony_ci # Dig through each result file, looking for details on pass/fail: 3635375f98Sopenharmony_ci for result_file in results: 3735375f98Sopenharmony_ci lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n'))) 3835375f98Sopenharmony_ci if len(lines) == 0: 3935375f98Sopenharmony_ci raise Exception("Empty test result file: %s" % result_file) 4035375f98Sopenharmony_ci 4135375f98Sopenharmony_ci # define an expression for your file reference 4235375f98Sopenharmony_ci entry_one = Combine( 4335375f98Sopenharmony_ci oneOf(list(alphas)) + ':/' + 4435375f98Sopenharmony_ci Word(alphanums + '_-./')) 4535375f98Sopenharmony_ci 4635375f98Sopenharmony_ci entry_two = Word(printables + ' ', excludeChars=':') 4735375f98Sopenharmony_ci entry = entry_one | entry_two 4835375f98Sopenharmony_ci 4935375f98Sopenharmony_ci delimiter = Literal(':').suppress() 5035375f98Sopenharmony_ci # Format of a result line is `[file_name]:line:test_name:RESULT[:msg]` 5135375f98Sopenharmony_ci tc_result_line = Group(ZeroOrMore(entry.setResultsName('tc_file_name')) 5235375f98Sopenharmony_ci + delimiter + entry.setResultsName('tc_line_nr') 5335375f98Sopenharmony_ci + delimiter + entry.setResultsName('tc_name') 5435375f98Sopenharmony_ci + delimiter + entry.setResultsName('tc_status') + 5535375f98Sopenharmony_ci Optional(delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line") 5635375f98Sopenharmony_ci 5735375f98Sopenharmony_ci eol = LineEnd().suppress() 5835375f98Sopenharmony_ci sol = LineStart().suppress() 5935375f98Sopenharmony_ci blank_line = sol + eol 6035375f98Sopenharmony_ci 6135375f98Sopenharmony_ci # Format of the summary line is `# Tests # Failures # Ignored` 6235375f98Sopenharmony_ci tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName( 6335375f98Sopenharmony_ci "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName( 6435375f98Sopenharmony_ci "tc_summary") 6535375f98Sopenharmony_ci tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result") 6635375f98Sopenharmony_ci 6735375f98Sopenharmony_ci # run it and see... 6835375f98Sopenharmony_ci pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line) 6935375f98Sopenharmony_ci pp1.ignore(blank_line | OneOrMore("-")) 7035375f98Sopenharmony_ci 7135375f98Sopenharmony_ci result = list() 7235375f98Sopenharmony_ci for l in lines: 7335375f98Sopenharmony_ci result.append((pp1.parseString(l)).asDict()) 7435375f98Sopenharmony_ci # delete empty results 7535375f98Sopenharmony_ci result = filter(None, result) 7635375f98Sopenharmony_ci 7735375f98Sopenharmony_ci tc_list = list() 7835375f98Sopenharmony_ci for r in result: 7935375f98Sopenharmony_ci if 'tc_line' in r: 8035375f98Sopenharmony_ci tmp_tc_line = r['tc_line'] 8135375f98Sopenharmony_ci 8235375f98Sopenharmony_ci # get only the file name which will be used as the classname 8335375f98Sopenharmony_ci if 'tc_file_name' in tmp_tc_line: 8435375f98Sopenharmony_ci file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0] 8535375f98Sopenharmony_ci else: 8635375f98Sopenharmony_ci file_name = result_file.strip("./") 8735375f98Sopenharmony_ci tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name) 8835375f98Sopenharmony_ci if 'tc_status' in tmp_tc_line: 8935375f98Sopenharmony_ci if str(tmp_tc_line['tc_status']) == 'IGNORE': 9035375f98Sopenharmony_ci if 'tc_msg' in tmp_tc_line: 9135375f98Sopenharmony_ci tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'], 9235375f98Sopenharmony_ci output=r'[File]={0}, [Line]={1}'.format( 9335375f98Sopenharmony_ci tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) 9435375f98Sopenharmony_ci else: 9535375f98Sopenharmony_ci tmp_tc.add_skipped_info(message=" ") 9635375f98Sopenharmony_ci elif str(tmp_tc_line['tc_status']) == 'FAIL': 9735375f98Sopenharmony_ci if 'tc_msg' in tmp_tc_line: 9835375f98Sopenharmony_ci tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'], 9935375f98Sopenharmony_ci output=r'[File]={0}, [Line]={1}'.format( 10035375f98Sopenharmony_ci tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) 10135375f98Sopenharmony_ci else: 10235375f98Sopenharmony_ci tmp_tc.add_failure_info(message=" ") 10335375f98Sopenharmony_ci 10435375f98Sopenharmony_ci tc_list.append((str(result_file), tmp_tc)) 10535375f98Sopenharmony_ci 10635375f98Sopenharmony_ci for k, v in tc_list: 10735375f98Sopenharmony_ci try: 10835375f98Sopenharmony_ci self.test_suites[k].append(v) 10935375f98Sopenharmony_ci except KeyError: 11035375f98Sopenharmony_ci self.test_suites[k] = [v] 11135375f98Sopenharmony_ci ts = [] 11235375f98Sopenharmony_ci for suite_name in self.test_suites: 11335375f98Sopenharmony_ci ts.append(TestSuite(suite_name, self.test_suites[suite_name])) 11435375f98Sopenharmony_ci 11535375f98Sopenharmony_ci with open(self.output, 'w') as f: 11635375f98Sopenharmony_ci TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8') 11735375f98Sopenharmony_ci 11835375f98Sopenharmony_ci return self.report 11935375f98Sopenharmony_ci 12035375f98Sopenharmony_ci def set_targets(self, target_array): 12135375f98Sopenharmony_ci self.targets = target_array 12235375f98Sopenharmony_ci 12335375f98Sopenharmony_ci def set_root_path(self, path): 12435375f98Sopenharmony_ci self.root = path 12535375f98Sopenharmony_ci 12635375f98Sopenharmony_ci def set_output(self, output): 12735375f98Sopenharmony_ci self.output = output 12835375f98Sopenharmony_ci 12935375f98Sopenharmony_ci 13035375f98Sopenharmony_ciif __name__ == '__main__': 13135375f98Sopenharmony_ci uts = UnityTestSummary() 13235375f98Sopenharmony_ci parser = argparse.ArgumentParser(description= 13335375f98Sopenharmony_ci """Takes as input the collection of *.testpass and *.testfail result 13435375f98Sopenharmony_ci files, and converts them to a JUnit formatted XML.""") 13535375f98Sopenharmony_ci parser.add_argument('targets_dir', metavar='result_file_directory', 13635375f98Sopenharmony_ci type=str, nargs='?', default='./', 13735375f98Sopenharmony_ci help="""The location of your results files. 13835375f98Sopenharmony_ci Defaults to current directory if not specified.""") 13935375f98Sopenharmony_ci parser.add_argument('root_path', nargs='?', 14035375f98Sopenharmony_ci default='os.path.split(__file__)[0]', 14135375f98Sopenharmony_ci help="""Helpful for producing more verbose output if 14235375f98Sopenharmony_ci using relative paths.""") 14335375f98Sopenharmony_ci parser.add_argument('--output', '-o', type=str, default="result.xml", 14435375f98Sopenharmony_ci help="""The name of the JUnit-formatted file (XML).""") 14535375f98Sopenharmony_ci args = parser.parse_args() 14635375f98Sopenharmony_ci 14735375f98Sopenharmony_ci if args.targets_dir[-1] != '/': 14835375f98Sopenharmony_ci args.targets_dir+='/' 14935375f98Sopenharmony_ci targets = list(map(lambda x: x.replace('\\', '/'), glob(args.targets_dir + '*.test*'))) 15035375f98Sopenharmony_ci if len(targets) == 0: 15135375f98Sopenharmony_ci raise Exception("No *.testpass or *.testfail files found in '%s'" % args.targets_dir) 15235375f98Sopenharmony_ci uts.set_targets(targets) 15335375f98Sopenharmony_ci 15435375f98Sopenharmony_ci # set the root path 15535375f98Sopenharmony_ci uts.set_root_path(args.root_path) 15635375f98Sopenharmony_ci 15735375f98Sopenharmony_ci # set output 15835375f98Sopenharmony_ci uts.set_output(args.output) 15935375f98Sopenharmony_ci 16035375f98Sopenharmony_ci # run the summarizer 16135375f98Sopenharmony_ci print(uts.run()) 162