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.
unity_to_junit.py
00001 # ----------------------------------------------------------------------- 00002 # Copyright (c) 2016 ARM Limited. All rights reserved. 00003 # SPDX-License-Identifier: Apache-2.0 00004 # Licensed under the Apache License, Version 2.0 (the License); you may 00005 # not use this file except in compliance with the License. 00006 # You may obtain a copy of the License at 00007 # 00008 # http://www.apache.org/licenses/LICENSE-2.0 00009 # 00010 # Unless required by applicable law or agreed to in writing, software 00011 # distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 # See the License for the specific language governing permissions and 00014 # limitations under the License. 00015 # ----------------------------------------------------------------------- 00016 00017 import re 00018 import sys 00019 from tabulate import tabulate 00020 00021 def extract_tags(logLines): 00022 00023 # These are the Unity tag names we are going to look for. 00024 tagNames = [ 00025 "UnityTest", 00026 "UnityIgnoredTest", 00027 "UnityResult", 00028 ] 00029 00030 # All tags will end up here. 00031 tags = [] 00032 00033 for tagName in tagNames: 00034 00035 # Fetch start and end locations for the start and end markers. 00036 00037 startMatches = re.finditer(re.escape("<***" + tagName + "***>"), logLines) 00038 endMatches = re.finditer(re.escape("</***" + tagName + "***>"), logLines) 00039 00040 startOffsets = [match.end() for match in startMatches] 00041 endOffsets = [match.start() - 1 for match in endMatches] 00042 00043 # If the amount of start and end markers isn't identical, this is an error. 00044 if len(startOffsets) != len(endOffsets): 00045 raise Exception("For tag '" + tagName + "', start and end tags do not match!") 00046 00047 # Append all found tags to the tags list. 00048 for tagOffsets in zip(startOffsets, endOffsets): 00049 tagContent = logLines[tagOffsets[0]: tagOffsets[1] + 1] 00050 tags.append((tagOffsets[0], tagName, tagContent)) 00051 00052 # Sort the tags list by the offset. 00053 tags.sort(key=lambda tag_: tag_[0]) 00054 00055 # Throw away the offset (once sorted, it is no longer needed). 00056 tags = [tag[1:] for tag in tags] 00057 00058 # At this point we are left with list of tags, each one a pair, consisting of 00059 # (group name, test name, status). 00060 return tags 00061 00062 def get_test_group_and_name(printableName): 00063 match = re.match(r"TEST\((.*), (.*)\)", printableName) 00064 if match is not None: 00065 return match.group(1), match.group(2) 00066 else: 00067 raise Exception("Erorr parsing test group and name") 00068 00069 def get_ignored_test_group_and_name(printableName): 00070 match = re.match(r"IGNORE_TEST\((.*), (.*)\)", printableName) 00071 if match is not None: 00072 return match.group(1), match.group(2) 00073 else: 00074 raise Exception("Erorr parsing test group and name") 00075 00076 def collect_tests(tags): 00077 00078 tests = [] 00079 00080 # Build the list of tests, with status for each. 00081 curTest = "" 00082 resultHandled = False 00083 for tag in tags: 00084 00085 tagName = tag[0] 00086 tagValue = tag[1] 00087 00088 if tagName == "UnityTest": 00089 curTest = get_test_group_and_name(tagValue) 00090 resultHandled = False 00091 elif tagName == "UnityResult": 00092 if not resultHandled: 00093 tests.append((curTest, tagValue)) 00094 resultHandled = True 00095 elif tagName == "UnityIgnoredTest": 00096 curTest = get_ignored_test_group_and_name(tagValue) 00097 tests.append((curTest, "IGNORE")) 00098 else: 00099 raise Exception("Unknown tag '" + tagName + "' encountered") 00100 00101 return tests 00102 00103 def generate_junit_xml_output(packageName, tests, xmlOutFile): 00104 00105 testsCount = len(tests) 00106 00107 with open(xmlOutFile, "wt") as f: 00108 print >> f, '<testsuite tests="' + str(testsCount) + '">' 00109 for test in tests: 00110 print >> f, ' <testcase classname="' + packageName + "." + test[0][0] + '" name="' + test[0][1] + '">' 00111 if test[1] == "FAIL": 00112 print >> f, ' <failure/>' 00113 if test[1] == "IGNORE": 00114 print >> f, ' <skipped/>' 00115 print >> f, ' </testcase>' 00116 print >> f, '</testsuite>' 00117 00118 def generate_text_output(packageName, tests, textOutFile): 00119 00120 testsCount = len(tests) 00121 00122 failingTests = 0 00123 passedTests = 0 00124 ignoredTests = 0 00125 00126 testsTable = [] 00127 for test in tests: 00128 if test[1] == "FAIL": 00129 failingTests += 1 00130 if test[1] == "PASS": 00131 passedTests += 1 00132 if test[1] == "IGNORE": 00133 ignoredTests += 1 00134 00135 testsTable.append([test[0][0], test[0][1], test[1]]) 00136 00137 resultsTableHeader = ["TOTAL", "PASS", "FAIL", "IGNORE"] 00138 resultsTable = [[str(testsCount), str(passedTests), str(failingTests), str(ignoredTests)]] 00139 00140 with open(textOutFile, "wt") as f: 00141 00142 print >> f, "==== " + packageName + " ====" 00143 print >> f, tabulate(testsTable) 00144 print >> f, tabulate(resultsTable, headers=resultsTableHeader) 00145 00146 if testsCount == 0 or failingTests > 0: 00147 finalStatus = "FAIL" 00148 else: 00149 finalStatus = "PASS" 00150 print >> f 00151 print >> f, "Final status: " + finalStatus + "." 00152 00153 def unity_to_junit(packageName, inputFile, xmlOutFile, textOutFile): 00154 00155 with open(inputFile, "rt") as f: 00156 logLines = f.read() 00157 00158 tags = extract_tags(logLines) 00159 tests = collect_tests(tags) 00160 00161 generate_junit_xml_output(packageName, tests, xmlOutFile) 00162 generate_text_output(packageName, tests, textOutFile) 00163 00164 00165 if __name__ == "__main__": 00166 00167 if len(sys.argv) != 5: 00168 print "Usage: <package-name> <input-file> <xml-out-file> <text-out-file>" 00169 sys.exit(1) 00170 00171 unity_to_junit(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]) 00172
Generated on Tue Jul 12 2022 21:20:32 by
1.7.2