14 """Generate XML and HTML test reports."""
17 from mako
import exceptions
18 from mako.runtime
import Context
19 from mako.template
import Template
25 import xml.etree.cElementTree
as ET
31 """Filters out nonprintable and illegal characters from the message."""
32 if output_format
in [
'XML',
'HTML']:
33 if isinstance(msg, bytes):
34 decoded_msg = msg.decode(
'UTF-8',
'ignore')
39 filtered_msg =
''.join(
40 filter(
lambda x: x
in string.printable
and x !=
'\f' and x !=
'\v',
42 if output_format ==
'HTML':
43 filtered_msg = filtered_msg.replace(
'"',
'"')
50 return ET.ElementTree(ET.Element(
'testsuites'))
59 """Generate JUnit-like XML report."""
68 for shortname, results
in six.iteritems(resultset):
69 one_result = {shortname: results}
72 '%s_%s' % (suite_package, shortname),
73 '%s_%s' % (suite_name, shortname),
'1',
75 per_suite_report_file = os.path.join(os.path.dirname(report_file),
77 os.path.basename(report_file))
82 """Generate JUnit-like report file from xml tree ."""
84 base_dir = os.getenv(
'GRPC_TEST_REPORT_BASE_DIR',
None)
86 report_file = os.path.join(base_dir, report_file)
88 report_dir = os.path.dirname(os.path.abspath(report_file))
89 if not os.path.exists(report_dir):
90 os.makedirs(report_dir)
91 tree.write(report_file, encoding=
'UTF-8')
100 """Append a JUnit-like XML report tree with test results as a new suite."""
105 suite_name = suite_name.replace(
'.',
'_')
106 testsuite = ET.SubElement(tree.getroot(),
109 package=suite_package,
111 timestamp=datetime.datetime.now().isoformat())
114 for shortname, results
in six.iteritems(resultset):
115 for result
in results:
116 xml_test = ET.SubElement(testsuite,
'testcase', name=shortname)
117 if result.elapsed_time:
118 xml_test.set(
'time',
str(result.elapsed_time))
120 if result.state ==
'FAILED':
121 ET.SubElement(xml_test,
'failure',
122 message=
'Failure').text = filtered_msg
124 elif result.state ==
'TIMEOUT':
125 ET.SubElement(xml_test,
'error',
126 message=
'Timeout').text = filtered_msg
128 elif result.state ==
'SKIPPED':
129 ET.SubElement(xml_test,
'skipped', message=
'Skipped')
130 testsuite.set(
'failures',
str(failure_count))
131 testsuite.set(
'errors',
str(error_count))
135 auth_test_cases, http2_cases, http2_server_cases,
136 resultset, num_failures, cloud_to_prod,
137 prod_servers, http2_interop):
138 """Generate HTML report for interop tests."""
139 template_file =
'tools/run_tests/interop/interop_html_report.template'
141 mytemplate = Template(filename=template_file, format_exceptions=
True)
144 'Mako template is not installed. Skipping HTML report generation.')
147 print((
'Failed to find the template %s: %s' % (template_file, e)))
150 sorted_test_cases = sorted(test_cases)
151 sorted_auth_test_cases = sorted(auth_test_cases)
152 sorted_http2_cases = sorted(http2_cases)
153 sorted_http2_server_cases = sorted(http2_server_cases)
154 sorted_client_langs = sorted(client_langs)
155 sorted_server_langs = sorted(server_langs)
156 sorted_prod_servers = sorted(prod_servers)
159 'client_langs': sorted_client_langs,
160 'server_langs': sorted_server_langs,
161 'test_cases': sorted_test_cases,
162 'auth_test_cases': sorted_auth_test_cases,
163 'http2_cases': sorted_http2_cases,
164 'http2_server_cases': sorted_http2_server_cases,
165 'resultset': resultset,
166 'num_failures': num_failures,
167 'cloud_to_prod': cloud_to_prod,
168 'prod_servers': sorted_prod_servers,
169 'http2_interop': http2_interop
172 html_report_out_dir =
'reports'
173 if not os.path.exists(html_report_out_dir):
174 os.mkdir(html_report_out_dir)
175 html_file_path = os.path.join(html_report_out_dir,
'index.html')
177 with open(html_file_path,
'w')
as output_file:
178 mytemplate.render_context(Context(output_file, **args))
180 print((exceptions.text_error_template().
render()))
185 with open(output_filepath,
'w')
as output_file:
186 output_file.write(
'<ul>\n')
187 for name
in profile_names:
188 output_file.write(
'<li><a href=%s>%s</a></li>\n' % (name, name))
189 output_file.write(
'</ul>\n')