takashi kadono
/
Nucleo446_SSD1331
Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466
mbed-os/tools/test_exporters.py@3:f3764f852aa8, 2018-10-11 (annotated)
- Committer:
- kadonotakashi
- Date:
- Thu Oct 11 02:27:46 2018 +0000
- Revision:
- 3:f3764f852aa8
- Parent:
- 0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kadonotakashi | 0:8fdf9a60065b | 1 | """ |
kadonotakashi | 0:8fdf9a60065b | 2 | mbed SDK |
kadonotakashi | 0:8fdf9a60065b | 3 | Copyright (c) 2011-2014 ARM Limited |
kadonotakashi | 0:8fdf9a60065b | 4 | |
kadonotakashi | 0:8fdf9a60065b | 5 | Licensed under the Apache License, Version 2.0 (the "License"); |
kadonotakashi | 0:8fdf9a60065b | 6 | you may not use this file except in compliance with the License. |
kadonotakashi | 0:8fdf9a60065b | 7 | You may obtain a copy of the License at |
kadonotakashi | 0:8fdf9a60065b | 8 | |
kadonotakashi | 0:8fdf9a60065b | 9 | http://www.apache.org/licenses/LICENSE-2.0 |
kadonotakashi | 0:8fdf9a60065b | 10 | |
kadonotakashi | 0:8fdf9a60065b | 11 | Unless required by applicable law or agreed to in writing, software |
kadonotakashi | 0:8fdf9a60065b | 12 | distributed under the License is distributed on an "AS IS" BASIS, |
kadonotakashi | 0:8fdf9a60065b | 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
kadonotakashi | 0:8fdf9a60065b | 14 | See the License for the specific language governing permissions and |
kadonotakashi | 0:8fdf9a60065b | 15 | limitations under the License. |
kadonotakashi | 0:8fdf9a60065b | 16 | |
kadonotakashi | 0:8fdf9a60065b | 17 | Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com> |
kadonotakashi | 0:8fdf9a60065b | 18 | """ |
kadonotakashi | 0:8fdf9a60065b | 19 | |
kadonotakashi | 0:8fdf9a60065b | 20 | from tools.utils import construct_enum, mkdir |
kadonotakashi | 0:8fdf9a60065b | 21 | from prettytable import PrettyTable |
kadonotakashi | 0:8fdf9a60065b | 22 | import os |
kadonotakashi | 0:8fdf9a60065b | 23 | |
kadonotakashi | 0:8fdf9a60065b | 24 | ResultExporterType = construct_enum(HTML='Html_Exporter', |
kadonotakashi | 0:8fdf9a60065b | 25 | JUNIT='JUnit_Exporter', |
kadonotakashi | 0:8fdf9a60065b | 26 | JUNIT_OPER='JUnit_Exporter_Interoperability', |
kadonotakashi | 0:8fdf9a60065b | 27 | BUILD='Build_Exporter', |
kadonotakashi | 0:8fdf9a60065b | 28 | TEXT='Text_Exporter', |
kadonotakashi | 0:8fdf9a60065b | 29 | PRINT='Print_Exporter') |
kadonotakashi | 0:8fdf9a60065b | 30 | |
kadonotakashi | 0:8fdf9a60065b | 31 | |
kadonotakashi | 0:8fdf9a60065b | 32 | class ReportExporter(): |
kadonotakashi | 0:8fdf9a60065b | 33 | """ Class exports extended test result Python data structure to |
kadonotakashi | 0:8fdf9a60065b | 34 | different formats like HTML, JUnit XML. |
kadonotakashi | 0:8fdf9a60065b | 35 | |
kadonotakashi | 0:8fdf9a60065b | 36 | Parameter 'test_result_ext' format: |
kadonotakashi | 0:8fdf9a60065b | 37 | |
kadonotakashi | 0:8fdf9a60065b | 38 | u'uARM': { u'LPC1768': { 'MBED_2': { 0: { 'copy_method': 'shutils.copy()', |
kadonotakashi | 0:8fdf9a60065b | 39 | 'duration': 20, |
kadonotakashi | 0:8fdf9a60065b | 40 | 'elapsed_time': 1.7929999828338623, |
kadonotakashi | 0:8fdf9a60065b | 41 | 'output': 'Host test instrumentation on ...\r\n', |
kadonotakashi | 0:8fdf9a60065b | 42 | 'result': 'OK', |
kadonotakashi | 0:8fdf9a60065b | 43 | 'target_name': u'LPC1768', |
kadonotakashi | 0:8fdf9a60065b | 44 | 'description': 'stdio', |
kadonotakashi | 0:8fdf9a60065b | 45 | 'id': u'MBED_2', |
kadonotakashi | 0:8fdf9a60065b | 46 | 'toolchain_name': u'uARM'}}, |
kadonotakashi | 0:8fdf9a60065b | 47 | """ |
kadonotakashi | 0:8fdf9a60065b | 48 | CSS_STYLE = """<style> |
kadonotakashi | 0:8fdf9a60065b | 49 | .name{ |
kadonotakashi | 0:8fdf9a60065b | 50 | border: 1px solid; |
kadonotakashi | 0:8fdf9a60065b | 51 | border-radius: 25px; |
kadonotakashi | 0:8fdf9a60065b | 52 | width: 100px; |
kadonotakashi | 0:8fdf9a60065b | 53 | } |
kadonotakashi | 0:8fdf9a60065b | 54 | .tooltip{ |
kadonotakashi | 0:8fdf9a60065b | 55 | position:absolute; |
kadonotakashi | 0:8fdf9a60065b | 56 | background-color: #F5DA81; |
kadonotakashi | 0:8fdf9a60065b | 57 | display:none; |
kadonotakashi | 0:8fdf9a60065b | 58 | } |
kadonotakashi | 0:8fdf9a60065b | 59 | </style> |
kadonotakashi | 0:8fdf9a60065b | 60 | """ |
kadonotakashi | 0:8fdf9a60065b | 61 | |
kadonotakashi | 0:8fdf9a60065b | 62 | JAVASCRIPT = """ |
kadonotakashi | 0:8fdf9a60065b | 63 | <script type="text/javascript"> |
kadonotakashi | 0:8fdf9a60065b | 64 | function show (elem) { |
kadonotakashi | 0:8fdf9a60065b | 65 | elem.style.display = "block"; |
kadonotakashi | 0:8fdf9a60065b | 66 | } |
kadonotakashi | 0:8fdf9a60065b | 67 | function hide (elem) { |
kadonotakashi | 0:8fdf9a60065b | 68 | elem.style.display = ""; |
kadonotakashi | 0:8fdf9a60065b | 69 | } |
kadonotakashi | 0:8fdf9a60065b | 70 | </script> |
kadonotakashi | 0:8fdf9a60065b | 71 | """ |
kadonotakashi | 0:8fdf9a60065b | 72 | |
kadonotakashi | 0:8fdf9a60065b | 73 | def __init__(self, result_exporter_type, package="test"): |
kadonotakashi | 0:8fdf9a60065b | 74 | self.result_exporter_type = result_exporter_type |
kadonotakashi | 0:8fdf9a60065b | 75 | self.package = package |
kadonotakashi | 0:8fdf9a60065b | 76 | |
kadonotakashi | 0:8fdf9a60065b | 77 | def report(self, test_summary_ext, test_suite_properties=None, |
kadonotakashi | 0:8fdf9a60065b | 78 | print_log_for_failures=True): |
kadonotakashi | 0:8fdf9a60065b | 79 | """ Invokes report depending on exporter_type set in constructor |
kadonotakashi | 0:8fdf9a60065b | 80 | """ |
kadonotakashi | 0:8fdf9a60065b | 81 | if self.result_exporter_type == ResultExporterType.HTML: |
kadonotakashi | 0:8fdf9a60065b | 82 | # HTML exporter |
kadonotakashi | 0:8fdf9a60065b | 83 | return self.exporter_html(test_summary_ext, test_suite_properties) |
kadonotakashi | 0:8fdf9a60065b | 84 | elif self.result_exporter_type == ResultExporterType.JUNIT: |
kadonotakashi | 0:8fdf9a60065b | 85 | # JUNIT exporter for results from test suite |
kadonotakashi | 0:8fdf9a60065b | 86 | return self.exporter_junit(test_summary_ext, test_suite_properties) |
kadonotakashi | 0:8fdf9a60065b | 87 | elif self.result_exporter_type == ResultExporterType.JUNIT_OPER: |
kadonotakashi | 0:8fdf9a60065b | 88 | # JUNIT exporter for interoperability test |
kadonotakashi | 0:8fdf9a60065b | 89 | return self.exporter_junit_ioper(test_summary_ext, test_suite_properties) |
kadonotakashi | 0:8fdf9a60065b | 90 | elif self.result_exporter_type == ResultExporterType.PRINT: |
kadonotakashi | 0:8fdf9a60065b | 91 | # JUNIT exporter for interoperability test |
kadonotakashi | 0:8fdf9a60065b | 92 | return self.exporter_print(test_summary_ext, print_log_for_failures=print_log_for_failures) |
kadonotakashi | 0:8fdf9a60065b | 93 | elif self.result_exporter_type == ResultExporterType.TEXT: |
kadonotakashi | 0:8fdf9a60065b | 94 | return self.exporter_text(test_summary_ext) |
kadonotakashi | 0:8fdf9a60065b | 95 | return None |
kadonotakashi | 0:8fdf9a60065b | 96 | |
kadonotakashi | 0:8fdf9a60065b | 97 | def report_to_file(self, test_summary_ext, file_name, test_suite_properties=None): |
kadonotakashi | 0:8fdf9a60065b | 98 | """ Stores report to specified file |
kadonotakashi | 0:8fdf9a60065b | 99 | """ |
kadonotakashi | 0:8fdf9a60065b | 100 | report = self.report(test_summary_ext, test_suite_properties=test_suite_properties) |
kadonotakashi | 0:8fdf9a60065b | 101 | self.write_to_file(report, file_name) |
kadonotakashi | 0:8fdf9a60065b | 102 | |
kadonotakashi | 0:8fdf9a60065b | 103 | def write_to_file(self, report, file_name): |
kadonotakashi | 0:8fdf9a60065b | 104 | if report is not None: |
kadonotakashi | 0:8fdf9a60065b | 105 | dirname = os.path.dirname(file_name) |
kadonotakashi | 0:8fdf9a60065b | 106 | if dirname: |
kadonotakashi | 0:8fdf9a60065b | 107 | mkdir(dirname) |
kadonotakashi | 0:8fdf9a60065b | 108 | with open(file_name, 'w') as f: |
kadonotakashi | 0:8fdf9a60065b | 109 | f.write(report) |
kadonotakashi | 0:8fdf9a60065b | 110 | |
kadonotakashi | 0:8fdf9a60065b | 111 | def get_tooltip_name(self, toolchain, target, test_id, loop_no): |
kadonotakashi | 0:8fdf9a60065b | 112 | """ Generate simple unique tool-tip name which can be used. |
kadonotakashi | 0:8fdf9a60065b | 113 | For example as HTML <div> section id attribute. |
kadonotakashi | 0:8fdf9a60065b | 114 | """ |
kadonotakashi | 0:8fdf9a60065b | 115 | return "target_test_%s_%s_%s_%s"% (toolchain.lower(), target.lower(), test_id.lower(), loop_no) |
kadonotakashi | 0:8fdf9a60065b | 116 | |
kadonotakashi | 0:8fdf9a60065b | 117 | def get_result_div_sections(self, test, test_no): |
kadonotakashi | 0:8fdf9a60065b | 118 | """ Generates separate <DIV> sections which contains test results output. |
kadonotakashi | 0:8fdf9a60065b | 119 | """ |
kadonotakashi | 0:8fdf9a60065b | 120 | |
kadonotakashi | 0:8fdf9a60065b | 121 | RESULT_COLORS = {'OK': 'LimeGreen', |
kadonotakashi | 0:8fdf9a60065b | 122 | 'FAIL': 'Orange', |
kadonotakashi | 0:8fdf9a60065b | 123 | 'ERROR': 'LightCoral', |
kadonotakashi | 0:8fdf9a60065b | 124 | 'OTHER': 'LightGray', |
kadonotakashi | 0:8fdf9a60065b | 125 | } |
kadonotakashi | 0:8fdf9a60065b | 126 | |
kadonotakashi | 0:8fdf9a60065b | 127 | tooltip_name = self.get_tooltip_name(test['toolchain_name'], test['target_name'], test['id'], test_no) |
kadonotakashi | 0:8fdf9a60065b | 128 | background_color = RESULT_COLORS[test['result'] if test['result'] in RESULT_COLORS else 'OTHER'] |
kadonotakashi | 0:8fdf9a60065b | 129 | result_div_style = "background-color: %s"% background_color |
kadonotakashi | 0:8fdf9a60065b | 130 | |
kadonotakashi | 0:8fdf9a60065b | 131 | result = """<div class="name" style="%s" onmouseover="show(%s)" onmouseout="hide(%s)"> |
kadonotakashi | 0:8fdf9a60065b | 132 | <center>%s</center> |
kadonotakashi | 0:8fdf9a60065b | 133 | <div class = "tooltip" id= "%s"> |
kadonotakashi | 0:8fdf9a60065b | 134 | <b>%s</b><br /> |
kadonotakashi | 0:8fdf9a60065b | 135 | <hr /> |
kadonotakashi | 0:8fdf9a60065b | 136 | <b>%s</b> in <b>%.2f sec</b><br /> |
kadonotakashi | 0:8fdf9a60065b | 137 | <hr /> |
kadonotakashi | 0:8fdf9a60065b | 138 | <small> |
kadonotakashi | 0:8fdf9a60065b | 139 | %s |
kadonotakashi | 0:8fdf9a60065b | 140 | </small> |
kadonotakashi | 0:8fdf9a60065b | 141 | </div> |
kadonotakashi | 0:8fdf9a60065b | 142 | </div> |
kadonotakashi | 0:8fdf9a60065b | 143 | """% (result_div_style, |
kadonotakashi | 0:8fdf9a60065b | 144 | tooltip_name, |
kadonotakashi | 0:8fdf9a60065b | 145 | tooltip_name, |
kadonotakashi | 0:8fdf9a60065b | 146 | test['result'], |
kadonotakashi | 0:8fdf9a60065b | 147 | tooltip_name, |
kadonotakashi | 0:8fdf9a60065b | 148 | test['target_name_unique'], |
kadonotakashi | 0:8fdf9a60065b | 149 | test['description'], |
kadonotakashi | 0:8fdf9a60065b | 150 | test['elapsed_time'], |
kadonotakashi | 0:8fdf9a60065b | 151 | test['output'].replace('\n', '<br />')) |
kadonotakashi | 0:8fdf9a60065b | 152 | return result |
kadonotakashi | 0:8fdf9a60065b | 153 | |
kadonotakashi | 0:8fdf9a60065b | 154 | def get_result_tree(self, test_results): |
kadonotakashi | 0:8fdf9a60065b | 155 | """ If test was run in a loop (we got few results from the same test) |
kadonotakashi | 0:8fdf9a60065b | 156 | we will show it in a column to see all results. |
kadonotakashi | 0:8fdf9a60065b | 157 | This function produces HTML table with corresponding results. |
kadonotakashi | 0:8fdf9a60065b | 158 | """ |
kadonotakashi | 0:8fdf9a60065b | 159 | result = '' |
kadonotakashi | 0:8fdf9a60065b | 160 | for i, test_result in enumerate(test_results): |
kadonotakashi | 0:8fdf9a60065b | 161 | result += '<table>' |
kadonotakashi | 0:8fdf9a60065b | 162 | test_ids = sorted(test_result.keys()) |
kadonotakashi | 0:8fdf9a60065b | 163 | for test_no in test_ids: |
kadonotakashi | 0:8fdf9a60065b | 164 | test = test_result[test_no] |
kadonotakashi | 0:8fdf9a60065b | 165 | result += """<tr> |
kadonotakashi | 0:8fdf9a60065b | 166 | <td valign="top">%s</td> |
kadonotakashi | 0:8fdf9a60065b | 167 | </tr>"""% self.get_result_div_sections(test, "%d_%d" % (test_no, i)) |
kadonotakashi | 0:8fdf9a60065b | 168 | result += '</table>' |
kadonotakashi | 0:8fdf9a60065b | 169 | return result |
kadonotakashi | 0:8fdf9a60065b | 170 | |
kadonotakashi | 0:8fdf9a60065b | 171 | def get_all_unique_test_ids(self, test_result_ext): |
kadonotakashi | 0:8fdf9a60065b | 172 | """ Gets all unique test ids from all ran tests. |
kadonotakashi | 0:8fdf9a60065b | 173 | We need this to create complete list of all test ran. |
kadonotakashi | 0:8fdf9a60065b | 174 | """ |
kadonotakashi | 0:8fdf9a60065b | 175 | result = [] |
kadonotakashi | 0:8fdf9a60065b | 176 | targets = test_result_ext.keys() |
kadonotakashi | 0:8fdf9a60065b | 177 | for target in targets: |
kadonotakashi | 0:8fdf9a60065b | 178 | toolchains = test_result_ext[target].keys() |
kadonotakashi | 0:8fdf9a60065b | 179 | for toolchain in toolchains: |
kadonotakashi | 0:8fdf9a60065b | 180 | tests = test_result_ext[target][toolchain].keys() |
kadonotakashi | 0:8fdf9a60065b | 181 | result.extend(tests) |
kadonotakashi | 0:8fdf9a60065b | 182 | return sorted(list(set(result))) |
kadonotakashi | 0:8fdf9a60065b | 183 | |
kadonotakashi | 0:8fdf9a60065b | 184 | # |
kadonotakashi | 0:8fdf9a60065b | 185 | # Exporters functions |
kadonotakashi | 0:8fdf9a60065b | 186 | # |
kadonotakashi | 0:8fdf9a60065b | 187 | |
kadonotakashi | 0:8fdf9a60065b | 188 | def exporter_html(self, test_result_ext, test_suite_properties=None): |
kadonotakashi | 0:8fdf9a60065b | 189 | """ Export test results in proprietary HTML format. |
kadonotakashi | 0:8fdf9a60065b | 190 | """ |
kadonotakashi | 0:8fdf9a60065b | 191 | result = """<html> |
kadonotakashi | 0:8fdf9a60065b | 192 | <head> |
kadonotakashi | 0:8fdf9a60065b | 193 | <title>mbed SDK test suite test result report</title> |
kadonotakashi | 0:8fdf9a60065b | 194 | %s |
kadonotakashi | 0:8fdf9a60065b | 195 | %s |
kadonotakashi | 0:8fdf9a60065b | 196 | </head> |
kadonotakashi | 0:8fdf9a60065b | 197 | <body> |
kadonotakashi | 0:8fdf9a60065b | 198 | """% (self.CSS_STYLE, self.JAVASCRIPT) |
kadonotakashi | 0:8fdf9a60065b | 199 | |
kadonotakashi | 0:8fdf9a60065b | 200 | unique_test_ids = self.get_all_unique_test_ids(test_result_ext) |
kadonotakashi | 0:8fdf9a60065b | 201 | targets = sorted(test_result_ext.keys()) |
kadonotakashi | 0:8fdf9a60065b | 202 | result += '<table>' |
kadonotakashi | 0:8fdf9a60065b | 203 | for target in targets: |
kadonotakashi | 0:8fdf9a60065b | 204 | toolchains = sorted(test_result_ext[target].keys()) |
kadonotakashi | 0:8fdf9a60065b | 205 | for toolchain in toolchains: |
kadonotakashi | 0:8fdf9a60065b | 206 | result += '<tr>' |
kadonotakashi | 0:8fdf9a60065b | 207 | result += '<td></td>' |
kadonotakashi | 0:8fdf9a60065b | 208 | result += '<td></td>' |
kadonotakashi | 0:8fdf9a60065b | 209 | |
kadonotakashi | 0:8fdf9a60065b | 210 | tests = sorted(test_result_ext[target][toolchain].keys()) |
kadonotakashi | 0:8fdf9a60065b | 211 | for test in unique_test_ids: |
kadonotakashi | 0:8fdf9a60065b | 212 | result += """<td align="center">%s</td>"""% test |
kadonotakashi | 0:8fdf9a60065b | 213 | result += """</tr> |
kadonotakashi | 0:8fdf9a60065b | 214 | <tr> |
kadonotakashi | 0:8fdf9a60065b | 215 | <td valign="center">%s</td> |
kadonotakashi | 0:8fdf9a60065b | 216 | <td valign="center"><b>%s</b></td> |
kadonotakashi | 0:8fdf9a60065b | 217 | """% (toolchain, target) |
kadonotakashi | 0:8fdf9a60065b | 218 | |
kadonotakashi | 0:8fdf9a60065b | 219 | for test in unique_test_ids: |
kadonotakashi | 0:8fdf9a60065b | 220 | test_result = self.get_result_tree(test_result_ext[target][toolchain][test]) if test in tests else '' |
kadonotakashi | 0:8fdf9a60065b | 221 | result += '<td>%s</td>'% (test_result) |
kadonotakashi | 0:8fdf9a60065b | 222 | |
kadonotakashi | 0:8fdf9a60065b | 223 | result += '</tr>' |
kadonotakashi | 0:8fdf9a60065b | 224 | result += '</table>' |
kadonotakashi | 0:8fdf9a60065b | 225 | result += '</body></html>' |
kadonotakashi | 0:8fdf9a60065b | 226 | return result |
kadonotakashi | 0:8fdf9a60065b | 227 | |
kadonotakashi | 0:8fdf9a60065b | 228 | def exporter_junit_ioper(self, test_result_ext, test_suite_properties=None): |
kadonotakashi | 0:8fdf9a60065b | 229 | from junit_xml import TestSuite, TestCase |
kadonotakashi | 0:8fdf9a60065b | 230 | test_suites = [] |
kadonotakashi | 0:8fdf9a60065b | 231 | test_cases = [] |
kadonotakashi | 0:8fdf9a60065b | 232 | |
kadonotakashi | 0:8fdf9a60065b | 233 | for platform in sorted(test_result_ext.keys()): |
kadonotakashi | 0:8fdf9a60065b | 234 | # {platform : ['Platform', 'Result', 'Scope', 'Description']) |
kadonotakashi | 0:8fdf9a60065b | 235 | test_cases = [] |
kadonotakashi | 0:8fdf9a60065b | 236 | for tr_result in test_result_ext[platform]: |
kadonotakashi | 0:8fdf9a60065b | 237 | result, name, scope, description = tr_result |
kadonotakashi | 0:8fdf9a60065b | 238 | |
kadonotakashi | 0:8fdf9a60065b | 239 | classname = 'test.ioper.%s.%s.%s' % (platform, name, scope) |
kadonotakashi | 0:8fdf9a60065b | 240 | elapsed_sec = 0 |
kadonotakashi | 0:8fdf9a60065b | 241 | _stdout = description |
kadonotakashi | 0:8fdf9a60065b | 242 | _stderr = '' |
kadonotakashi | 0:8fdf9a60065b | 243 | # Test case |
kadonotakashi | 0:8fdf9a60065b | 244 | tc = TestCase(name, classname, elapsed_sec, _stdout, _stderr) |
kadonotakashi | 0:8fdf9a60065b | 245 | # Test case extra failure / error info |
kadonotakashi | 0:8fdf9a60065b | 246 | if result == 'FAIL': |
kadonotakashi | 0:8fdf9a60065b | 247 | tc.add_failure_info(description, _stdout) |
kadonotakashi | 0:8fdf9a60065b | 248 | elif result == 'ERROR': |
kadonotakashi | 0:8fdf9a60065b | 249 | tc.add_error_info(description, _stdout) |
kadonotakashi | 0:8fdf9a60065b | 250 | elif result == 'SKIP' or result == 'NOT_SUPPORTED': |
kadonotakashi | 0:8fdf9a60065b | 251 | tc.add_skipped_info(description, _stdout) |
kadonotakashi | 0:8fdf9a60065b | 252 | |
kadonotakashi | 0:8fdf9a60065b | 253 | test_cases.append(tc) |
kadonotakashi | 0:8fdf9a60065b | 254 | ts = TestSuite("test.suite.ioper.%s" % (platform), test_cases) |
kadonotakashi | 0:8fdf9a60065b | 255 | test_suites.append(ts) |
kadonotakashi | 0:8fdf9a60065b | 256 | return TestSuite.to_xml_string(test_suites) |
kadonotakashi | 0:8fdf9a60065b | 257 | |
kadonotakashi | 0:8fdf9a60065b | 258 | def exporter_junit(self, test_result_ext, test_suite_properties=None): |
kadonotakashi | 0:8fdf9a60065b | 259 | """ Export test results in JUnit XML compliant format |
kadonotakashi | 0:8fdf9a60065b | 260 | """ |
kadonotakashi | 0:8fdf9a60065b | 261 | from junit_xml import TestSuite, TestCase |
kadonotakashi | 0:8fdf9a60065b | 262 | test_suites = [] |
kadonotakashi | 0:8fdf9a60065b | 263 | test_cases = [] |
kadonotakashi | 0:8fdf9a60065b | 264 | |
kadonotakashi | 0:8fdf9a60065b | 265 | targets = sorted(test_result_ext.keys()) |
kadonotakashi | 0:8fdf9a60065b | 266 | for target in targets: |
kadonotakashi | 0:8fdf9a60065b | 267 | toolchains = sorted(test_result_ext[target].keys()) |
kadonotakashi | 0:8fdf9a60065b | 268 | for toolchain in toolchains: |
kadonotakashi | 0:8fdf9a60065b | 269 | test_cases = [] |
kadonotakashi | 0:8fdf9a60065b | 270 | tests = sorted(test_result_ext[target][toolchain].keys()) |
kadonotakashi | 0:8fdf9a60065b | 271 | for test in tests: |
kadonotakashi | 0:8fdf9a60065b | 272 | test_results = test_result_ext[target][toolchain][test] |
kadonotakashi | 0:8fdf9a60065b | 273 | for test_res in test_results: |
kadonotakashi | 0:8fdf9a60065b | 274 | test_ids = sorted(test_res.keys()) |
kadonotakashi | 0:8fdf9a60065b | 275 | for test_no in test_ids: |
kadonotakashi | 0:8fdf9a60065b | 276 | test_result = test_res[test_no] |
kadonotakashi | 0:8fdf9a60065b | 277 | name = test_result['description'] |
kadonotakashi | 0:8fdf9a60065b | 278 | classname = '%s.%s.%s.%s'% (self.package, target, toolchain, test_result['id']) |
kadonotakashi | 0:8fdf9a60065b | 279 | elapsed_sec = test_result['elapsed_time'] |
kadonotakashi | 0:8fdf9a60065b | 280 | _stdout = test_result['output'] |
kadonotakashi | 0:8fdf9a60065b | 281 | |
kadonotakashi | 0:8fdf9a60065b | 282 | if 'target_name_unique' in test_result: |
kadonotakashi | 0:8fdf9a60065b | 283 | _stderr = test_result['target_name_unique'] |
kadonotakashi | 0:8fdf9a60065b | 284 | else: |
kadonotakashi | 0:8fdf9a60065b | 285 | _stderr = test_result['target_name'] |
kadonotakashi | 0:8fdf9a60065b | 286 | |
kadonotakashi | 0:8fdf9a60065b | 287 | # Test case |
kadonotakashi | 0:8fdf9a60065b | 288 | tc = TestCase(name, classname, elapsed_sec, _stdout, _stderr) |
kadonotakashi | 0:8fdf9a60065b | 289 | |
kadonotakashi | 0:8fdf9a60065b | 290 | # Test case extra failure / error info |
kadonotakashi | 0:8fdf9a60065b | 291 | message = test_result['result'] |
kadonotakashi | 0:8fdf9a60065b | 292 | if test_result['result'] == 'FAIL': |
kadonotakashi | 0:8fdf9a60065b | 293 | tc.add_failure_info(message, _stdout) |
kadonotakashi | 0:8fdf9a60065b | 294 | elif test_result['result'] == 'SKIP' or test_result["result"] == 'NOT_SUPPORTED': |
kadonotakashi | 0:8fdf9a60065b | 295 | tc.add_skipped_info(message, _stdout) |
kadonotakashi | 0:8fdf9a60065b | 296 | elif test_result['result'] != 'OK': |
kadonotakashi | 0:8fdf9a60065b | 297 | tc.add_error_info(message, _stdout) |
kadonotakashi | 0:8fdf9a60065b | 298 | |
kadonotakashi | 0:8fdf9a60065b | 299 | test_cases.append(tc) |
kadonotakashi | 0:8fdf9a60065b | 300 | |
kadonotakashi | 0:8fdf9a60065b | 301 | ts = TestSuite("test.suite.%s.%s"% (target, toolchain), test_cases, properties=test_suite_properties[target][toolchain]) |
kadonotakashi | 0:8fdf9a60065b | 302 | test_suites.append(ts) |
kadonotakashi | 0:8fdf9a60065b | 303 | return TestSuite.to_xml_string(test_suites) |
kadonotakashi | 0:8fdf9a60065b | 304 | |
kadonotakashi | 0:8fdf9a60065b | 305 | def exporter_print_helper(self, array, print_log=False): |
kadonotakashi | 0:8fdf9a60065b | 306 | for item in array: |
kadonotakashi | 0:8fdf9a60065b | 307 | print(" * %s::%s::%s" % (item["target_name"], |
kadonotakashi | 0:8fdf9a60065b | 308 | item["toolchain_name"], |
kadonotakashi | 0:8fdf9a60065b | 309 | item["id"])) |
kadonotakashi | 0:8fdf9a60065b | 310 | if print_log: |
kadonotakashi | 0:8fdf9a60065b | 311 | log_lines = item["output"].split("\n") |
kadonotakashi | 0:8fdf9a60065b | 312 | for log_line in log_lines: |
kadonotakashi | 0:8fdf9a60065b | 313 | print(" %s" % log_line) |
kadonotakashi | 0:8fdf9a60065b | 314 | |
kadonotakashi | 0:8fdf9a60065b | 315 | def exporter_print(self, test_result_ext, print_log_for_failures=False): |
kadonotakashi | 0:8fdf9a60065b | 316 | """ Export test results in print format. |
kadonotakashi | 0:8fdf9a60065b | 317 | """ |
kadonotakashi | 0:8fdf9a60065b | 318 | failures = [] |
kadonotakashi | 0:8fdf9a60065b | 319 | skips = [] |
kadonotakashi | 0:8fdf9a60065b | 320 | successes = [] |
kadonotakashi | 0:8fdf9a60065b | 321 | |
kadonotakashi | 0:8fdf9a60065b | 322 | unique_test_ids = self.get_all_unique_test_ids(test_result_ext) |
kadonotakashi | 0:8fdf9a60065b | 323 | targets = sorted(test_result_ext.keys()) |
kadonotakashi | 0:8fdf9a60065b | 324 | |
kadonotakashi | 0:8fdf9a60065b | 325 | for target in targets: |
kadonotakashi | 0:8fdf9a60065b | 326 | toolchains = sorted(test_result_ext[target].keys()) |
kadonotakashi | 0:8fdf9a60065b | 327 | for toolchain in toolchains: |
kadonotakashi | 0:8fdf9a60065b | 328 | tests = sorted(test_result_ext[target][toolchain].keys()) |
kadonotakashi | 0:8fdf9a60065b | 329 | for test in tests: |
kadonotakashi | 0:8fdf9a60065b | 330 | test_runs = test_result_ext[target][toolchain][test] |
kadonotakashi | 0:8fdf9a60065b | 331 | for test_runner in test_runs: |
kadonotakashi | 0:8fdf9a60065b | 332 | #test_run = test_result_ext[target][toolchain][test][test_run_number][0] |
kadonotakashi | 0:8fdf9a60065b | 333 | test_run = test_runner[0] |
kadonotakashi | 0:8fdf9a60065b | 334 | |
kadonotakashi | 0:8fdf9a60065b | 335 | if "result" in test_run: |
kadonotakashi | 0:8fdf9a60065b | 336 | if test_run["result"] == "FAIL": |
kadonotakashi | 0:8fdf9a60065b | 337 | failures.append(test_run) |
kadonotakashi | 0:8fdf9a60065b | 338 | elif test_run["result"] == "SKIP" or test_run["result"] == "NOT_SUPPORTED": |
kadonotakashi | 0:8fdf9a60065b | 339 | skips.append(test_run) |
kadonotakashi | 0:8fdf9a60065b | 340 | elif test_run["result"] == "OK": |
kadonotakashi | 0:8fdf9a60065b | 341 | successes.append(test_run) |
kadonotakashi | 0:8fdf9a60065b | 342 | else: |
kadonotakashi | 0:8fdf9a60065b | 343 | raise Exception("Unhandled result type: %s" % (test_run["result"])) |
kadonotakashi | 0:8fdf9a60065b | 344 | else: |
kadonotakashi | 0:8fdf9a60065b | 345 | raise Exception("'test_run' did not have a 'result' value") |
kadonotakashi | 0:8fdf9a60065b | 346 | |
kadonotakashi | 0:8fdf9a60065b | 347 | if successes: |
kadonotakashi | 0:8fdf9a60065b | 348 | print("\n\nBuild successes:") |
kadonotakashi | 0:8fdf9a60065b | 349 | self.exporter_print_helper(successes) |
kadonotakashi | 0:8fdf9a60065b | 350 | |
kadonotakashi | 0:8fdf9a60065b | 351 | if skips: |
kadonotakashi | 0:8fdf9a60065b | 352 | print("\n\nBuild skips:") |
kadonotakashi | 0:8fdf9a60065b | 353 | self.exporter_print_helper(skips) |
kadonotakashi | 0:8fdf9a60065b | 354 | |
kadonotakashi | 0:8fdf9a60065b | 355 | if failures: |
kadonotakashi | 0:8fdf9a60065b | 356 | print("\n\nBuild failures:") |
kadonotakashi | 0:8fdf9a60065b | 357 | self.exporter_print_helper(failures, print_log=print_log_for_failures) |
kadonotakashi | 0:8fdf9a60065b | 358 | return False |
kadonotakashi | 0:8fdf9a60065b | 359 | else: |
kadonotakashi | 0:8fdf9a60065b | 360 | return True |
kadonotakashi | 0:8fdf9a60065b | 361 | |
kadonotakashi | 0:8fdf9a60065b | 362 | def exporter_text(self, test_result_ext): |
kadonotakashi | 0:8fdf9a60065b | 363 | """ Prints well-formed summary with results (SQL table like) |
kadonotakashi | 0:8fdf9a60065b | 364 | table shows target x test results matrix across |
kadonotakashi | 0:8fdf9a60065b | 365 | """ |
kadonotakashi | 0:8fdf9a60065b | 366 | success_code = 0 # Success code that can be leter returned to |
kadonotakashi | 0:8fdf9a60065b | 367 | # Pretty table package is used to print results |
kadonotakashi | 0:8fdf9a60065b | 368 | pt = PrettyTable(["Result", "Target", "Toolchain", "Test ID", "Test Description", |
kadonotakashi | 0:8fdf9a60065b | 369 | "Elapsed Time", "Timeout"]) |
kadonotakashi | 0:8fdf9a60065b | 370 | pt.align["Result"] = "l" # Left align |
kadonotakashi | 0:8fdf9a60065b | 371 | pt.align["Target"] = "l" # Left align |
kadonotakashi | 0:8fdf9a60065b | 372 | pt.align["Toolchain"] = "l" # Left align |
kadonotakashi | 0:8fdf9a60065b | 373 | pt.align["Test ID"] = "l" # Left align |
kadonotakashi | 0:8fdf9a60065b | 374 | pt.align["Test Description"] = "l" # Left align |
kadonotakashi | 0:8fdf9a60065b | 375 | pt.padding_width = 1 # One space between column edges and contents (default) |
kadonotakashi | 0:8fdf9a60065b | 376 | |
kadonotakashi | 0:8fdf9a60065b | 377 | result_dict = {"OK" : 0, |
kadonotakashi | 0:8fdf9a60065b | 378 | "FAIL" : 0, |
kadonotakashi | 0:8fdf9a60065b | 379 | "ERROR" : 0, |
kadonotakashi | 0:8fdf9a60065b | 380 | "UNDEF" : 0, |
kadonotakashi | 0:8fdf9a60065b | 381 | "IOERR_COPY" : 0, |
kadonotakashi | 0:8fdf9a60065b | 382 | "IOERR_DISK" : 0, |
kadonotakashi | 0:8fdf9a60065b | 383 | "IOERR_SERIAL" : 0, |
kadonotakashi | 0:8fdf9a60065b | 384 | "TIMEOUT" : 0, |
kadonotakashi | 0:8fdf9a60065b | 385 | "NO_IMAGE" : 0, |
kadonotakashi | 0:8fdf9a60065b | 386 | "MBED_ASSERT" : 0, |
kadonotakashi | 0:8fdf9a60065b | 387 | "BUILD_FAILED" : 0, |
kadonotakashi | 0:8fdf9a60065b | 388 | "NOT_SUPPORTED" : 0 |
kadonotakashi | 0:8fdf9a60065b | 389 | } |
kadonotakashi | 0:8fdf9a60065b | 390 | unique_test_ids = self.get_all_unique_test_ids(test_result_ext) |
kadonotakashi | 0:8fdf9a60065b | 391 | targets = sorted(test_result_ext.keys()) |
kadonotakashi | 0:8fdf9a60065b | 392 | for target in targets: |
kadonotakashi | 0:8fdf9a60065b | 393 | toolchains = sorted(test_result_ext[target].keys()) |
kadonotakashi | 0:8fdf9a60065b | 394 | for toolchain in toolchains: |
kadonotakashi | 0:8fdf9a60065b | 395 | test_cases = [] |
kadonotakashi | 0:8fdf9a60065b | 396 | tests = sorted(test_result_ext[target][toolchain].keys()) |
kadonotakashi | 0:8fdf9a60065b | 397 | for test in tests: |
kadonotakashi | 0:8fdf9a60065b | 398 | test_results = test_result_ext[target][toolchain][test] |
kadonotakashi | 0:8fdf9a60065b | 399 | for test_res in test_results: |
kadonotakashi | 0:8fdf9a60065b | 400 | test_ids = sorted(test_res.keys()) |
kadonotakashi | 0:8fdf9a60065b | 401 | for test_no in test_ids: |
kadonotakashi | 0:8fdf9a60065b | 402 | test_result = test_res[test_no] |
kadonotakashi | 0:8fdf9a60065b | 403 | result_dict[test_result['result']] += 1 |
kadonotakashi | 0:8fdf9a60065b | 404 | pt.add_row([test_result['result'], |
kadonotakashi | 0:8fdf9a60065b | 405 | test_result['target_name'], |
kadonotakashi | 0:8fdf9a60065b | 406 | test_result['toolchain_name'], |
kadonotakashi | 0:8fdf9a60065b | 407 | test_result['id'], |
kadonotakashi | 0:8fdf9a60065b | 408 | test_result['description'], |
kadonotakashi | 0:8fdf9a60065b | 409 | test_result['elapsed_time'], |
kadonotakashi | 0:8fdf9a60065b | 410 | test_result['duration']]) |
kadonotakashi | 0:8fdf9a60065b | 411 | result = pt.get_string() |
kadonotakashi | 0:8fdf9a60065b | 412 | result += "\n" |
kadonotakashi | 0:8fdf9a60065b | 413 | |
kadonotakashi | 0:8fdf9a60065b | 414 | # Print result count |
kadonotakashi | 0:8fdf9a60065b | 415 | result += "Result: " + ' / '.join(['%s %s' % (value, key) for (key, value) in {k: v for k, v in result_dict.items() if v != 0}.items()]) |
kadonotakashi | 0:8fdf9a60065b | 416 | return result |