Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pal/Test/Unity/auto/unity_to_junit.py@0:06ee5f8a484a, 2017-03-18 (annotated)
- Committer:
- djmeyers
- Date:
- Sat Mar 18 22:37:16 2017 +0000
- Revision:
- 0:06ee5f8a484a
Initial commit
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| djmeyers | 0:06ee5f8a484a | 1 | import sys |
| djmeyers | 0:06ee5f8a484a | 2 | import os |
| djmeyers | 0:06ee5f8a484a | 3 | from glob import glob |
| djmeyers | 0:06ee5f8a484a | 4 | |
| djmeyers | 0:06ee5f8a484a | 5 | from pyparsing import * |
| djmeyers | 0:06ee5f8a484a | 6 | from junit_xml import TestSuite, TestCase |
| djmeyers | 0:06ee5f8a484a | 7 | |
| djmeyers | 0:06ee5f8a484a | 8 | |
| djmeyers | 0:06ee5f8a484a | 9 | class UnityTestSummary: |
| djmeyers | 0:06ee5f8a484a | 10 | def __init__(self): |
| djmeyers | 0:06ee5f8a484a | 11 | self.report = '' |
| djmeyers | 0:06ee5f8a484a | 12 | self.total_tests = 0 |
| djmeyers | 0:06ee5f8a484a | 13 | self.failures = 0 |
| djmeyers | 0:06ee5f8a484a | 14 | self.ignored = 0 |
| djmeyers | 0:06ee5f8a484a | 15 | self.targets = 0 |
| djmeyers | 0:06ee5f8a484a | 16 | self.root = None |
| djmeyers | 0:06ee5f8a484a | 17 | self.test_suites = dict() |
| djmeyers | 0:06ee5f8a484a | 18 | |
| djmeyers | 0:06ee5f8a484a | 19 | def run(self): |
| djmeyers | 0:06ee5f8a484a | 20 | # Clean up result file names |
| djmeyers | 0:06ee5f8a484a | 21 | results = [] |
| djmeyers | 0:06ee5f8a484a | 22 | for target in self.targets: |
| djmeyers | 0:06ee5f8a484a | 23 | results.append(target.replace('\\', '/')) |
| djmeyers | 0:06ee5f8a484a | 24 | |
| djmeyers | 0:06ee5f8a484a | 25 | # Dig through each result file, looking for details on pass/fail: |
| djmeyers | 0:06ee5f8a484a | 26 | for result_file in results: |
| djmeyers | 0:06ee5f8a484a | 27 | lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n'))) |
| djmeyers | 0:06ee5f8a484a | 28 | if len(lines) == 0: |
| djmeyers | 0:06ee5f8a484a | 29 | raise Exception("Empty test result file: %s" % result_file) |
| djmeyers | 0:06ee5f8a484a | 30 | |
| djmeyers | 0:06ee5f8a484a | 31 | # define an expression for your file reference |
| djmeyers | 0:06ee5f8a484a | 32 | entry_one = Combine( |
| djmeyers | 0:06ee5f8a484a | 33 | oneOf(list(alphas)) + ':/' + |
| djmeyers | 0:06ee5f8a484a | 34 | Word(alphanums + '_-./')) |
| djmeyers | 0:06ee5f8a484a | 35 | |
| djmeyers | 0:06ee5f8a484a | 36 | entry_two = Word(printables + ' ', excludeChars=':') |
| djmeyers | 0:06ee5f8a484a | 37 | entry = entry_one | entry_two |
| djmeyers | 0:06ee5f8a484a | 38 | |
| djmeyers | 0:06ee5f8a484a | 39 | delimiter = Literal(':').suppress() |
| djmeyers | 0:06ee5f8a484a | 40 | tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName( |
| djmeyers | 0:06ee5f8a484a | 41 | 'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName( |
| djmeyers | 0:06ee5f8a484a | 42 | 'tc_status') + Optional( |
| djmeyers | 0:06ee5f8a484a | 43 | delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line") |
| djmeyers | 0:06ee5f8a484a | 44 | |
| djmeyers | 0:06ee5f8a484a | 45 | eol = LineEnd().suppress() |
| djmeyers | 0:06ee5f8a484a | 46 | sol = LineStart().suppress() |
| djmeyers | 0:06ee5f8a484a | 47 | blank_line = sol + eol |
| djmeyers | 0:06ee5f8a484a | 48 | |
| djmeyers | 0:06ee5f8a484a | 49 | tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName( |
| djmeyers | 0:06ee5f8a484a | 50 | "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName( |
| djmeyers | 0:06ee5f8a484a | 51 | "tc_summary") |
| djmeyers | 0:06ee5f8a484a | 52 | tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result") |
| djmeyers | 0:06ee5f8a484a | 53 | |
| djmeyers | 0:06ee5f8a484a | 54 | # run it and see... |
| djmeyers | 0:06ee5f8a484a | 55 | pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line) |
| djmeyers | 0:06ee5f8a484a | 56 | pp1.ignore(blank_line | OneOrMore("-")) |
| djmeyers | 0:06ee5f8a484a | 57 | |
| djmeyers | 0:06ee5f8a484a | 58 | result = list() |
| djmeyers | 0:06ee5f8a484a | 59 | for l in lines: |
| djmeyers | 0:06ee5f8a484a | 60 | result.append((pp1.parseString(l)).asDict()) |
| djmeyers | 0:06ee5f8a484a | 61 | # delete empty results |
| djmeyers | 0:06ee5f8a484a | 62 | result = filter(None, result) |
| djmeyers | 0:06ee5f8a484a | 63 | |
| djmeyers | 0:06ee5f8a484a | 64 | tc_list = list() |
| djmeyers | 0:06ee5f8a484a | 65 | for r in result: |
| djmeyers | 0:06ee5f8a484a | 66 | if 'tc_line' in r: |
| djmeyers | 0:06ee5f8a484a | 67 | tmp_tc_line = r['tc_line'] |
| djmeyers | 0:06ee5f8a484a | 68 | |
| djmeyers | 0:06ee5f8a484a | 69 | # get only the file name which will be used as the classname |
| djmeyers | 0:06ee5f8a484a | 70 | file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0] |
| djmeyers | 0:06ee5f8a484a | 71 | tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name) |
| djmeyers | 0:06ee5f8a484a | 72 | if 'tc_status' in tmp_tc_line: |
| djmeyers | 0:06ee5f8a484a | 73 | if str(tmp_tc_line['tc_status']) == 'IGNORE': |
| djmeyers | 0:06ee5f8a484a | 74 | if 'tc_msg' in tmp_tc_line: |
| djmeyers | 0:06ee5f8a484a | 75 | tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'], |
| djmeyers | 0:06ee5f8a484a | 76 | output=r'[File]={0}, [Line]={1}'.format( |
| djmeyers | 0:06ee5f8a484a | 77 | tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) |
| djmeyers | 0:06ee5f8a484a | 78 | else: |
| djmeyers | 0:06ee5f8a484a | 79 | tmp_tc.add_skipped_info(message=" ") |
| djmeyers | 0:06ee5f8a484a | 80 | elif str(tmp_tc_line['tc_status']) == 'FAIL': |
| djmeyers | 0:06ee5f8a484a | 81 | if 'tc_msg' in tmp_tc_line: |
| djmeyers | 0:06ee5f8a484a | 82 | tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'], |
| djmeyers | 0:06ee5f8a484a | 83 | output=r'[File]={0}, [Line]={1}'.format( |
| djmeyers | 0:06ee5f8a484a | 84 | tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) |
| djmeyers | 0:06ee5f8a484a | 85 | else: |
| djmeyers | 0:06ee5f8a484a | 86 | tmp_tc.add_failure_info(message=" ") |
| djmeyers | 0:06ee5f8a484a | 87 | |
| djmeyers | 0:06ee5f8a484a | 88 | tc_list.append((str(result_file), tmp_tc)) |
| djmeyers | 0:06ee5f8a484a | 89 | |
| djmeyers | 0:06ee5f8a484a | 90 | for k, v in tc_list: |
| djmeyers | 0:06ee5f8a484a | 91 | try: |
| djmeyers | 0:06ee5f8a484a | 92 | self.test_suites[k].append(v) |
| djmeyers | 0:06ee5f8a484a | 93 | except KeyError: |
| djmeyers | 0:06ee5f8a484a | 94 | self.test_suites[k] = [v] |
| djmeyers | 0:06ee5f8a484a | 95 | ts = [] |
| djmeyers | 0:06ee5f8a484a | 96 | for suite_name in self.test_suites: |
| djmeyers | 0:06ee5f8a484a | 97 | ts.append(TestSuite(suite_name, self.test_suites[suite_name])) |
| djmeyers | 0:06ee5f8a484a | 98 | |
| djmeyers | 0:06ee5f8a484a | 99 | with open('result.xml', 'w') as f: |
| djmeyers | 0:06ee5f8a484a | 100 | TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8') |
| djmeyers | 0:06ee5f8a484a | 101 | |
| djmeyers | 0:06ee5f8a484a | 102 | return self.report |
| djmeyers | 0:06ee5f8a484a | 103 | |
| djmeyers | 0:06ee5f8a484a | 104 | def set_targets(self, target_array): |
| djmeyers | 0:06ee5f8a484a | 105 | self.targets = target_array |
| djmeyers | 0:06ee5f8a484a | 106 | |
| djmeyers | 0:06ee5f8a484a | 107 | def set_root_path(self, path): |
| djmeyers | 0:06ee5f8a484a | 108 | self.root = path |
| djmeyers | 0:06ee5f8a484a | 109 | |
| djmeyers | 0:06ee5f8a484a | 110 | @staticmethod |
| djmeyers | 0:06ee5f8a484a | 111 | def usage(err_msg=None): |
| djmeyers | 0:06ee5f8a484a | 112 | print("\nERROR: ") |
| djmeyers | 0:06ee5f8a484a | 113 | if err_msg: |
| djmeyers | 0:06ee5f8a484a | 114 | print(err_msg) |
| djmeyers | 0:06ee5f8a484a | 115 | print("\nUsage: unity_test_summary.py result_file_directory/ root_path/") |
| djmeyers | 0:06ee5f8a484a | 116 | print(" result_file_directory - The location of your results files.") |
| djmeyers | 0:06ee5f8a484a | 117 | print(" Defaults to current directory if not specified.") |
| djmeyers | 0:06ee5f8a484a | 118 | print(" Should end in / if specified.") |
| djmeyers | 0:06ee5f8a484a | 119 | print(" root_path - Helpful for producing more verbose output if using relative paths.") |
| djmeyers | 0:06ee5f8a484a | 120 | sys.exit(1) |
| djmeyers | 0:06ee5f8a484a | 121 | |
| djmeyers | 0:06ee5f8a484a | 122 | |
| djmeyers | 0:06ee5f8a484a | 123 | if __name__ == '__main__': |
| djmeyers | 0:06ee5f8a484a | 124 | uts = UnityTestSummary() |
| djmeyers | 0:06ee5f8a484a | 125 | try: |
| djmeyers | 0:06ee5f8a484a | 126 | # look in the specified or current directory for result files |
| djmeyers | 0:06ee5f8a484a | 127 | if len(sys.argv) > 1: |
| djmeyers | 0:06ee5f8a484a | 128 | targets_dir = sys.argv[1] |
| djmeyers | 0:06ee5f8a484a | 129 | else: |
| djmeyers | 0:06ee5f8a484a | 130 | targets_dir = './' |
| djmeyers | 0:06ee5f8a484a | 131 | targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*'))) |
| djmeyers | 0:06ee5f8a484a | 132 | if len(targets) == 0: |
| djmeyers | 0:06ee5f8a484a | 133 | raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir) |
| djmeyers | 0:06ee5f8a484a | 134 | uts.set_targets(targets) |
| djmeyers | 0:06ee5f8a484a | 135 | |
| djmeyers | 0:06ee5f8a484a | 136 | # set the root path |
| djmeyers | 0:06ee5f8a484a | 137 | if len(sys.argv) > 2: |
| djmeyers | 0:06ee5f8a484a | 138 | root_path = sys.argv[2] |
| djmeyers | 0:06ee5f8a484a | 139 | else: |
| djmeyers | 0:06ee5f8a484a | 140 | root_path = os.path.split(__file__)[0] |
| djmeyers | 0:06ee5f8a484a | 141 | uts.set_root_path(root_path) |
| djmeyers | 0:06ee5f8a484a | 142 | |
| djmeyers | 0:06ee5f8a484a | 143 | # run the summarizer |
| djmeyers | 0:06ee5f8a484a | 144 | print(uts.run()) |
| djmeyers | 0:06ee5f8a484a | 145 | except Exception as e: |
| djmeyers | 0:06ee5f8a484a | 146 | UnityTestSummary.usage(e) |