def pytest_html_results_table_row(report, cells): try: cells.insert(2, html.td(report.description)) cells.insert(3, html.td(datetime.datetime.utcnow(), class_='col-time')) cells.pop() except: print("error occur, cannot update report")
def _generate_environment(self, environment_details): rows = [] keys = [ k for k in environment_details.keys() if environment_details[k] ] if not isinstance(environment_details, OrderedDict): keys.sort() for key in keys: value = environment_details[key] if isinstance(value, basestring) and value.startswith("http"): value = html.a(value, href=value, target="_blank") elif isinstance(value, (list, tuple, set)): value = ", ".join((str(i) for i in value)) rows.append(html.tr(html.td(key), html.td(value))) environment = html.div( html.h2("Environment"), html.div( html.table(rows, id="environment"), class_="environment-info", ), class_="environment-details", ) return environment
def version_get(self, user, index, name, version): stage = self.getstage(user, index) name = ensure_unicode(name) version = ensure_unicode(version) metadata = stage.get_projectconfig(name) if not metadata: abort(404, "project %r does not exist" % name) verdata = metadata.get(version, None) if not verdata: abort(404, "version %r does not exist" % version) if json_preferred(): apireturn(200, type="versiondata", result=verdata) # if html show description and metadata rows = [] for key, value in sorted(verdata.items()): if key == "description": continue if isinstance(value, list): value = html.ul([html.li(x) for x in value]) rows.append(html.tr(html.td(key), html.td(value))) title = "%s/: %s-%s metadata and description" % (stage.name, name, version) content = stage.get_description(name, version) #css = "https://pypi.python.org/styles/styles.css" return simple_html_body( title, [html.table(*rows), py.xml.raw(content)], extrahead=[ html.link(media="screen", type="text/css", rel="stylesheet", title="text", href="https://pypi.python.org/styles/styles.css") ]).unicode(indent=2)
def _generate_environment(self, config): if not hasattr(config, "_metadata") or config._metadata is None: return [] metadata = config._metadata environment = [html.h2("Environment")] rows = [] keys = [k for k in metadata.keys()] if not isinstance(metadata, OrderedDict): keys.sort() for key in keys: value = metadata[key] if isinstance(value, str) and value.startswith("http"): value = html.a(value, href=value, target="_blank") elif isinstance(value, (list, tuple, set)): value = ", ".join(str(i) for i in sorted(map(str, value))) elif isinstance(value, dict): key_value_list = [f"'{k}': {value[k]}" for k in sorted(value)] value = ", ".join(key_value_list) value = "{" + value + "}" raw_value_string = raw(str(value)) rows.append(html.tr(html.td(key), html.td(raw_value_string))) environment.append(html.table(rows, id="environment")) return environment
def pytest_html_results_table_row(report, cells): ''' Description列添加详情和Test_nodeid列添加详情,删除原有的的Test列 ''' cells.insert(1, html.td(report.description)) cells.insert(2, html.td(report.nodeid)) cells.pop(2)
def pytest_html_results_table_row(report, cells): if hasattr(report, '_batch') and report._batch: score = "-0" # unable to resovle the domain subresult_html = [] if report._score: score = report._score[0] for k in sorted(report._subresults[0].keys()): subresult_html.append(make_result_square(k, report._subresults[0][k])) subresult_html.append(html.span(f'{report._reference}', style='padding-left: 5px')) if len(report._subresults) > 1: subresult_html.append(html.br()) for k in sorted(report._subresults[0].keys()): if k in report._subresults[1]: result = report._subresults[1].pop(k) else: result = None subresult_html.append(make_result_square(k, result)) for k in sorted(report._subresults[1].keys()): subresult_html.append(make_result_square(k, report._subresults[1][k])) subresult_html.append(html.span(f'{report._demo}', style='padding-left: 5px')) score = report._score[1] - score cells[1] = html.td(sortsafe(report._fqdn)) cells.insert(2, html.td(sortsafe(score))) cells.insert(3, html.td(sortsafe(subresult_html), style='font_family:monospace')) cells.insert(4, html.td(sortsafe(br_join(report._failures)))) cells.insert(5, html.td(sortsafe(br_join(report._warnings))))
def pytest_html_results_table_row(report, cells): if hasattr(report, "user_properties"): props = {k: v for k, v in report.user_properties} cells.insert(2, html.td(props["solver"])) cells.insert(3, html.td(props["checker"] if "checker" in props else "-")) cells.pop()
def version_get(self, user, index, name, version): stage = self.getstage(user, index) name = ensure_unicode(name) version = ensure_unicode(version) metadata = stage.get_projectconfig(name) if not metadata: abort(404, "project %r does not exist" % name) verdata = metadata.get(version, None) if not verdata: abort(404, "version %r does not exist" % version) if json_preferred(): apireturn(200, type="versiondata", result=verdata) # if html show description and metadata rows = [] for key, value in sorted(verdata.items()): if key == "description": continue if isinstance(value, list): value = html.ul([html.li(x) for x in value]) rows.append(html.tr(html.td(key), html.td(value))) title = "%s/: %s-%s metadata and description" % ( stage.name, name, version) content = stage.get_description(name, version) #css = "https://pypi.python.org/styles/styles.css" return simple_html_body(title, [html.table(*rows), py.xml.raw(content)], extrahead= [html.link(media="screen", type="text/css", rel="stylesheet", title="text", href="https://pypi.python.org/styles/styles.css")] ).unicode(indent=2)
def pytest_html_results_table_row(report, cells): if "CC FAIL" in report.longreprtext: cells[0] = html.td("CC FAIL", class_="col-result") test_start_time = datetime.fromtimestamp( report.test_start_time).strftime("%d-%m-%Y %H:%M:%S:%f") cells.insert(0, html.td(test_start_time, class_="col-time"))
def add_row(self, lineno, text): if text == ['']: text = [raw(' ')] else: text = prepare_line(text, self.tokenizer, self.encoding) self.tbody.append(html.tr(html.td(str(lineno), class_='lineno'), html.td(class_='code', *text)))
def __init__(self, outcome, report, self_contained, logfile): self.test_id = report.nodeid if report.when != 'call': self.test_id = '::'.join([report.nodeid, report.when]) self.time = getattr(report, 'duration', 0.0) self.outcome = outcome self.additional_html = [] self.links_html = [] self.self_contained = self_contained self.logfile = logfile test_index = hasattr(report, 'rerun') and report.rerun + 1 or 0 for extra_index, extra in enumerate(getattr(report, 'extra', [])): self.append_extra_html(extra, extra_index, test_index) xfail = hasattr(report, 'wasxfail') if (report.skipped and xfail) or (report.failed and not xfail): self.append_log_html(report, self.additional_html) self.row_table = html.tr([ html.td(self.outcome, class_='col-result'), html.td(self.test_id, class_='col-name'), html.td('{0:.2f}'.format(self.time), class_='col-duration'), html.td(self.links_html, class_='col-links') ]) self.row_extra = html.tr( html.td(self.additional_html, class_='extra', colspan='5'))
def pytest_html_results_table_row(report, cells): waveform = html.td("N/A") if report.trace: waveform = html.td(html.a("waveform-trace", href=report.trace)) cells.insert(2, waveform) cells.pop()
def pytest_html_results_table_row(report, cells): try: cells.insert(2, html.td(report.module_name)) # 模块名称 cells.insert(3, html.td(report.description)) # 用例描述 cells.pop() except: pass
def pytest_html_results_table_row(report, cells): """ Inserts the contents for the 'description' column : the docstring of the test function """ node_bits = report.nodeid.split('::') file = node_bits[0] test_id = node_bits[1:] line = report.location[1] cells[1] = html.th(file) cells.insert(2, html.td('::'.join(test_id) if len(node_bits) > 1 else '')) cells.insert(3, html.td(report.description)) # cells.insert(1, html.td(datetime.utcnow(), class_='col-time')) # cells.pop() # use setuptools_scm to get git hash and build the codecov URL to go and see the source of the test # parsed_version = version_from_scm('.') # if parsed_version is not None: # hsh = parsed_version.node + ('' if not parsed_version.dirty else '-dirty') try: hsh = get_git_hash() cells[-1] = html.td( html.a('source', href='https://codecov.io/gh/smarie/python-valid8/src/' + hsh + '/' + file + '#L' + str(line))) except: cells[-1] = html.td('could not read git version')
def _generate_environment(self, config): if not hasattr(config, "_metadata") or config._metadata is None: return [] metadata = config._metadata environment = [html.h2("测试环境")] rows = [] keys = [k for k in metadata.keys()] # if not isinstance(metadata, OrderedDict): # keys.sort() for key in keys: value = metadata[key] if isinstance(value, str) and value.startswith("http"): value = html.a(value, href=value, target="_blank") elif isinstance(value, (list, tuple, set)): value = ", ".join(str(i) for i in sorted(map(str, value))) elif isinstance(value, dict): sorted_dict = {k: value[k] for k in sorted(value)} value = json.dumps(sorted_dict) raw_value_string = raw(str(value)) rows.append(html.tr(html.td(TEST_ENV.get(key)), html.td(raw_value_string))) environment.append(html.table(rows, id="environment")) return environment
def make_table_rows(self): regressions = self.results.regressions rv = [] tests = sorted(regressions.keys()) for i, test in enumerate(tests): test_data = regressions[test] cells, needs_subtest = self.make_test_name(test, test_data, i) for subtest in sorted(test_data.keys()): if needs_subtest: cells.append(html.td(subtest)) subtest_data = test_data[subtest] cells.extend([ html.td(subtest_data["expected"].title(), class_="condition %s" % subtest_data["expected"]), html.td(subtest_data["status"].title(), class_="condition %s" % subtest_data["status"]), html.td(subtest_data.get("message", ""), class_="message") ]) tr = html.tr(cells) rv.append(tr) cells = [] needs_subtest = True return rv
def _appendrow(self, result_name, report): time = getattr(report, 'duration', 0.0) additional_html = [] links_html = [] for extra in getattr(report, 'extra', []): self.append_extra_html(extra, additional_html, links_html) self.append_log_html(report, additional_html) test_id = report.nodeid if report.when != 'call': test_id = '::'.join([report.nodeid, report.when]) rows_table = html.tr([ html.td(result_name, class_='col-result'), html.td(test_id, class_='col-name'), html.td('{0:.2f}'.format(time), class_='col-duration'), html.td(links_html, class_='col-links')]) rows_extra = html.tr(html.td(additional_html, class_='extra', colspan='5')) self.test_logs.append(html.tbody(rows_table, rows_extra, class_=result_name.lower() + ' results-table-row'))
def make_test_name(self, test, test_data, index): pos_cls = "even" if index % 2 else "odd" test_name = self.test_string(test) if len(test_data) == 1 and None in test_data.keys(): return [html.td(test_name, colspan=2, class_="parent_test %s" % pos_cls)], False else: return [html.td(test_name, rowspan=len(test_data), class_="parent_test %s" % pos_cls)], True
def _generate_environment(self, config): if not hasattr(config, "_metadata") or config._metadata is None: return [] metadata = config._metadata if 'Capabilities' in metadata: metadata.pop('Capabilities') if 'Base URL' in config._metadata: metadata.pop('Base URL') environment = [html.h2("Environment")] rows = [] keys = [k for k in metadata.keys()] if not isinstance(metadata, OrderedDict): keys.sort() for key in keys: value = metadata[key] if isinstance(value, str) and value.startswith("http"): value = html.a(value, href=value, target="_blank") elif isinstance(value, (list, tuple, set)): value = ", ".join(str(i) for i in value) rows.append(html.tr(html.td(key), html.td(value))) environment.append(html.table(rows, id="environment")) return environment
def pytest_html_results_table_row(report, cells): if not hasattr(report, "description"): cells.insert(2, html.td(str(report.longrepr))) else: cells.insert(2, html.td(report.description)) cells.insert(1, html.td(datetime.utcnow(), class_="col-time")) cells.pop()
def _appendrow(self, result, report): time = getattr(report, 'duration', 0.0) additional_html = [] links_html = [] for extra in getattr(report, 'extra', []): href = None if extra.get('format') == extras.FORMAT_IMAGE: href = '#' image = 'data:image/png;base64,%s' % extra.get('content') additional_html.append(html.div( html.a(html.img(src=image), href="#"), class_='image')) elif extra.get('format') == extras.FORMAT_HTML: additional_html.append(extra.get('content')) elif extra.get('format') == extras.FORMAT_JSON: href = data_uri(json.dumps(extra.get('content')), mime_type='application/json') elif extra.get('format') == extras.FORMAT_TEXT: href = data_uri(extra.get('content')) elif extra.get('format') == extras.FORMAT_URL: href = extra.get('content') if href is not None: links_html.append(html.a( extra.get('name'), class_=extra.get('format'), href=href, target='_blank')) links_html.append(' ') if 'Passed' not in result: if report.longrepr: log = html.div(class_='log') for line in str(report.longrepr).splitlines(): if not PY3: line = line.decode('utf-8') separator = line.startswith('_ ' * 10) if separator: log.append(line[:80]) else: exception = line.startswith("E ") if exception: log.append(html.span(raw(escape(line)), class_='error')) else: log.append(raw(escape(line))) log.append(html.br()) additional_html.append(log) self.test_logs.append(html.tr([ html.td(result, class_='col-result'), html.td(report.nodeid, class_='col-name'), html.td('%.2f' % time, class_='col-duration'), html.td(links_html, class_='col-links'), html.td(additional_html, class_='extra')], class_=result.lower() + ' results-table-row'))
def make_result_html(self, data): tc_time = (data["time"] - self.start_times.pop(data["test"])) / 1000. additional_html = [] debug = data.get("extra", {}) links_html = [] status = status_name = data["status"] expected = data.get("expected", status) if status != expected: status_name = "UNEXPECTED_" + status elif status != "PASS": status_name = "EXPECTED_" + status self.test_count[status_name] += 1 if status in ['SKIP', 'FAIL', 'ERROR']: if debug.get('screenshot'): screenshot = 'data:image/png;base64,%s' % debug['screenshot'] additional_html.append(html.div( html.a(html.img(src=screenshot), href="#"), class_='screenshot')) for name, content in debug.items(): if 'screenshot' in name: href = '#' else: # use base64 to avoid that some browser (such as Firefox, Opera) # treats '#' as the start of another link if the data URL contains. # use 'charset=utf-8' to show special characters like Chinese. href = 'data:text/plain;charset=utf-8;base64,%s' % base64.b64encode(content.encode('utf-8')) links_html.append(html.a( name.title(), class_=name, href=href, target='_blank')) links_html.append(' ') log = html.div(class_='log') output = data.get('stack', '').splitlines() output.extend(data.get('message', '').splitlines()) for line in output: separator = line.startswith(' ' * 10) if separator: log.append(line[:80]) else: if line.lower().find("error") != -1 or line.lower().find("exception") != -1: log.append(html.span(raw(cgi.escape(line)), class_='error')) else: log.append(raw(cgi.escape(line))) log.append(html.br()) additional_html.append(log) self.result_rows.append( html.tr([html.td(status_name, class_='col-result'), html.td(data['test'], class_='col-name'), html.td('%.2f' % tc_time, class_='col-duration'), html.td(links_html, class_='col-links'), html.td(additional_html, class_='debug')], class_=status_name.lower() + ' results-table-row'))
def pytest_html_results_table_row(report, cells): cells.insert(1, html.td(report.description)) cells.insert(2, html.td(report.nodeid)) cells.pop(3) cells.insert(3, html.td(report.URL)) cells.insert(4, html.td(report.assertions)) cells.insert(-2, html.td(report.exec_time, class_='col-time')) cells.pop()
def pytest_html_results_table_row(report, cells): '''Adding values to columns of HTML Report, Description and Time Executed ''' if hasattr(report, "description"): cells.insert(2, html.td(report.description)) else: cells.insert(2, html.td("None")) cells.insert(1, html.td(arrow.now(), class_='col-time'))
def pytest_html_results_table_row(report, cells): """ Add content to the column Description """ try: cells.insert(2, html.td(report.description)) except AttributeError: cells.insert(2, html.td('--- no description ---'))
def pytest_html_results_table_row(report, cells): try: cells.insert(4, html.td(report.tier)) cells.insert(3, html.td(report.markers)) cells.insert(2, html.td(report.description)) cells.insert(1, html.td(datetime.utcnow(), class_='col-time')) except AttributeError: pass
def make_errors_table(self, errors): rows = [] for error in errors: rows.append(html.tr( html.td(error["level"], class_="log_%s" % error["level"]), html.td(error.get("message", "")) )) return html.table(rows, id_="errors")
def _appendrow(self, result, report): time = getattr(report, 'duration', 0.0) additional_html = [] links_html = [] if 'Passed' not in result: for extra in getattr(report, 'extra', []): href = None if type(extra) is Image: href = '#' image = 'data:image/png;base64,%s' % extra.content additional_html.append(html.div( html.a(html.img(src=image), href="#"), class_='image')) elif type(extra) is HTML: additional_html.append(extra.content) elif type(extra) is Text: href = 'data:text/plain;charset=utf-8;base64,%s' % \ b64encode(extra.content) elif type(extra) is URL: href = extra.content if href is not None: links_html.append(html.a( extra.name, class_=extra.__class__.__name__.lower(), href=href, target='_blank')) links_html.append(' ') if report.longrepr: log = html.div(class_='log') for line in str(report.longrepr).splitlines(): line = line.decode('utf-8') separator = line.startswith('_ ' * 10) if separator: log.append(line[:80]) else: exception = line.startswith("E ") if exception: log.append(html.span(raw(cgi.escape(line)), class_='error')) else: log.append(raw(cgi.escape(line))) log.append(html.br()) additional_html.append(log) self.test_logs.append(html.tr([ html.td(result, class_='col-result'), html.td(report.nodeid, class_='col-name'), html.td('%.2f' % time, class_='col-duration'), html.td(links_html, class_='col-links'), html.td(additional_html, class_='extra')], class_=result.lower() + ' results-table-row'))
def pytest_html_results_table_row(report, cells): cells.insert( 2, html.td(report.description, style="white-space:pre-wrap; word-wrap:break-word")) cells.insert( 3, html.td(datetime.now(timezone(timedelta(hours=+9), "JST")).strftime("%Y/%m/%d %H:%M:%S"), class_="col-time"))
def _create_overview(self): for node, results in self.tempDict.iteritems(): table = [html.td(node, class_="col-name")] res = [ html.td(result.capitalize(), class_="%s col-%s" % (result.lower(), when)) for when, result in results.iteritems() ] table.extend(res) self.test_overview.append(html.tr(table))
def make_body(self): body_parts = [ html.div( html.script(raw( pkg_resources.resource_string( rcname, os.path.sep.join( ['resources', 'htmlreport', 'jquery.js']))), type='text/javascript'), html.script(raw( pkg_resources.resource_string( rcname, os.path.sep.join( ['resources', 'htmlreport', 'main.js']))), type='text/javascript'), html.h1("FirefoxOS Certification Suite Report"), html.p("Run at %s" % self.time.strftime("%Y-%m-%d %H:%M:%S"))) ] if self.logs: device_profile_object = None with open(self.logs[-1]) as f: device_profile_object = json.load(f)['result']['contact'] device_profile = [html.h2('Device Information')] device_table = html.table() for key in device_profile_object: device_table.append( html.tr(html.td(key), html.td(device_profile_object[key]))) #device_profile.append(html.p("%s, %s"% (key, device_profile_object[key]))) device_profile.append(device_table) body_parts.extend(device_profile) if self.summary_results.has_errors: body_parts.append(html.h2("Errors During Run")) body_parts.append( self.make_errors_table(self.summary_results.errors)) body_parts.append(html.h2("Test Results")) body_parts.append(self.make_result_table()) if self.logs: ulbody = [] for log_path in self.logs: details_log = '' with open(log_path, 'r') as f: details_log = f.read() href = 'data:text/plain;charset=utf-8;base64,%s' % base64.b64encode( details_log) ulbody.append( html.li( html.a(os.path.basename(log_path), href=href, target='_blank'))) device_profile_object = None body_parts.append(html.h2("Details log information")) body_parts.append(html.ul(ulbody)) return html.body(body_parts)
def tabelize(value): try: rows = [] for key in value.keys(): rows.append(html.tr(html.td(html.pre(key)), html.td(tabelize(value[key])))) return html.table(rows) except AttributeError: if type(value) == type([]): return html.table(map(tabelize, value)) else: return html.pre(value)
def pytest_html_results_table_row(report, cells): cells.insert( 2, html.td(report.description) ) # 用pytest_runtest_makereport()钩子函数里的report.description变量给每行复制 cells.insert(1, html.td(report.nodeid) ) # 用pytest_runtest_makereport()钩子函数里的report.nodeid变量给每行复制 cells.insert( 1, html.td(datetime.utcnow(), class_='col-time')) # utcnow()是获取当前时间,用当前时间给Time列的每行赋值 cells.pop(3) # 删除Test列的行内容 cells.pop() # 删除Link列的行内容
def __init__(self, outcome, report, logfile, config): self.test_id = report.nodeid.encode("utf-8").decode( "unicode_escape") if getattr(report, "when", "call") != "call": self.test_id = "::".join([report.nodeid, report.when]) self.time = getattr(report, "duration", 0.0) self.formatted_time = self._format_time(report) self.outcome = outcome self.additional_html = [] self.links_html = [] self.self_contained = config.getoption("self_contained_html") self.max_asset_filename_length = int( config.getini("max_asset_filename_length")) self.logfile = logfile self.config = config self.row_table = self.row_extra = None test_index = hasattr(report, "rerun") and report.rerun + 1 or 0 for extra_index, extra in enumerate(getattr(report, "extra", [])): self.append_extra_html(extra, extra_index, test_index) self.append_log_html( report, self.additional_html, config.option.capture, config.option.showcapture, ) cells = [ html.td(self.outcome, class_="col-result"), html.td(self.test_id, class_="col-name"), html.td(self.formatted_time, class_="col-duration"), html.td(self.links_html, class_="col-links"), ] self.config.hook.pytest_html_results_table_row(report=report, cells=cells) self.config.hook.pytest_html_results_table_html( report=report, data=self.additional_html) if len(cells) > 0: tr_class = None if self.config.getini("render_collapsed"): tr_class = "collapsed" self.row_table = html.tr(cells) self.row_extra = html.tr( html.td(self.additional_html, class_="extra", colspan=len(cells)), class_=tr_class, )
def generate_html(self): generated = datetime.utcnow() with open(os.path.join(base_path, "main.js")) as main_f: doc = html.html( self.head, html.body( html.script(raw(main_f.read())), html.p('Report generated on %s at %s' % (generated.strftime('%d-%b-%Y'), generated.strftime('%H:%M:%S'))), html.h2('Environment'), html.table([ html.tr(html.td(k), html.td(v)) for k, v in sorted(self.env.items()) if v ], id='environment'), html.h2('Summary'), html.p( '%i tests ran in %.1f seconds.' % (sum(self.test_count.itervalues()), (self.suite_times["end"] - self.suite_times["start"]) / 1000.), html.br(), html.span('%i passed' % self.test_count["PASS"], class_='pass'), ', ', html.span('%i skipped' % self.test_count["SKIP"], class_='skip'), ', ', html.span('%i failed' % self.test_count["UNEXPECTED_FAIL"], class_='fail'), ', ', html.span('%i errors' % self.test_count["UNEXPECTED_ERROR"], class_='error'), '.', html.br(), html.span('%i expected failures' % self.test_count["EXPECTED_FAIL"], class_='expected_fail'), ', ', html.span('%i unexpected passes' % self.test_count["UNEXPECTED_PASS"], class_='unexpected_pass'), '.'), html.h2('Results'), html.table([ html.thead(html.tr([ html.th('Result', class_='sortable', col='result'), html.th('Test', class_='sortable', col='name'), html.th('Duration', class_='sortable numeric', col='duration'), html.th('Links') ]), id='results-table-head'), html.tbody(self.result_rows, id='results-table-body') ], id='results-table'))) return u"<!DOCTYPE html>\n" + doc.unicode(indent=2)
def tabelize(value): try: rows = [] for key in value.keys(): rows.append( html.tr(html.td(html.pre(key)), html.td(tabelize(value[key])))) return html.table(rows) except AttributeError: if type(value) == type([]): return html.table(map(tabelize, value)) else: return html.pre(value)
def _create_test_steps_tr(self, test_step_main_div, user_id, status_code, request_headers_main_div): test_steps_tr = html.tr(class_="steps_table_tr") test_steps_tr.append( html.td(test_step_main_div, class_="tr_step_name")) test_steps_tr.append( html.td(raw(user_id), class_="tr_step_user_id")) test_steps_tr.append( html.td(raw(status_code), class_="tr_step_status_code")) test_steps_tr.append( html.td(request_headers_main_div, class_="tr_step_request_headers")) return test_steps_tr
def __init__(self, outcome, report, logfile, config): #self.test_id = report.nodeid self.test_id = (' ::').join(report.nodeid.split('::')) if getattr(report, 'when', 'call') != 'call': self.test_id = ' ::'.join([report.nodeid, report.when]) self.time = getattr(report, 'duration', 0.00) self.outcome = outcome self.additional_html = [] self.links_html = [] self.self_contained = config.getoption('self_contained_html') self.logfile = logfile self.config = config self.row_table = self.row_extra = None test_index = hasattr(report, 'rerun') and report.rerun + 1 or 0 for extra_index, extra in enumerate(getattr(report, 'extra', [])): self.append_extra_html(extra, extra_index, test_index) self.append_log_html(report, self.additional_html) #add description if hasattr(report, "description"): des = report.description else: des = "无" cells = [ html.td(self.outcome, class_='col-result'), html.td(des, class_='col-description'), #des html.td(self.test_id, class_='col-name'), html.td('{0:.2f}'.format(self.time), class_='col-duration') #,html.td(self.links_html, class_='col-links') ] self.config.hook.pytest_html_results_table_row(report=report, cells=cells) self.config.hook.pytest_html_results_table_html( report=report, data=self.additional_html) if len(cells) > 0: self.row_table = html.tr(cells) self.row_extra = html.tr( html.td(self.additional_html, class_='extra', colspan=len(cells)))
def make_body(self): body_parts = [html.div( html.script(raw(pkg_resources.resource_string( rcname, os.path.sep.join(['resources', 'htmlreport', 'jquery.js']))), type='text/javascript'), html.script(raw(pkg_resources.resource_string( rcname, os.path.sep.join(['resources', 'htmlreport', 'main.js']))), type='text/javascript'), html.h1("FirefoxOS Certification Suite Report"), html.p("Run at %s" % self.time.strftime("%Y-%m-%d %H:%M:%S")) )] if self.logs: device_profile_object = None with open(self.logs[-1]) as f: device_profile_object = json.load(f)['result']['contact'] device_profile = [html.h2('Device Information')] device_table = html.table() for key in device_profile_object: device_table.append( html.tr( html.td(key), html.td(device_profile_object[key]) ) ) #device_profile.append(html.p("%s, %s"% (key, device_profile_object[key]))) device_profile.append(device_table) body_parts.extend(device_profile); if self.summary_results.has_errors: body_parts.append(html.h2("Errors During Run")) body_parts.append(self.make_errors_table(self.summary_results.errors)) body_parts.append(html.h2("Test Results")) body_parts.append(self.make_result_table()) if self.logs: ulbody = []; for log_path in self.logs: details_log = '' with open(log_path, 'r') as f: details_log = f.read() href = 'data:text/plain;charset=utf-8;base64,%s' % base64.b64encode(details_log) ulbody.append(html.li(html.a(os.path.basename(log_path), href=href, target='_blank'))) device_profile_object = None body_parts.append(html.h2("Details log information")) body_parts.append(html.ul(ulbody)) return html.body(body_parts)
def _generate_environment(self, config): if not hasattr(config, '_metadata') or config._metadata is None: return [] metadata = config._metadata environment = [html.h2('Environment')] rows = [] for key in [k for k in sorted(metadata.keys()) if metadata[k]]: value = metadata[key] if isinstance(value, basestring) and value.startswith('http'): value = html.a(value, href=value, target='_blank') rows.append(html.tr(html.td(key), html.td(value))) environment.append(html.table(rows, id='environment')) return environment
def pytest_html_results_table_row(report, cells): """ Called after building results table row. """ try: test_steps = [ step for step in re.split('\n *', report.description) if len(step) > 0 ] html_test_steps = list(map(lambda step: html.p(step), test_steps)) test_file_path, test_class, test_name = re.search( '>(.*)<', str(cells[1])).groups()[0].split("::") cells[1] = html.td(test_name, class_='col-name') cells.insert(2, html.td(html_test_steps)) cells.insert(0, html.td(datetime.utcnow(), class_='col-time')) cells.pop() except Exception as e: pass
def create_dir_html(path, href_prefix=''): h = html.html( html.head( html.title('directory listing of %s' % (path,)), style, ), ) body = html.body( html.h1('directory listing of %s' % (path,)), ) h.append(body) table = html.table() body.append(table) tbody = html.tbody() table.append(tbody) items = list(path.listdir()) items.sort(key=lambda p: p.basename) items.sort(key=lambda p: not p.check(dir=True)) for fpath in items: tr = html.tr() tbody.append(tr) td1 = html.td(fpath.check(dir=True) and 'D' or 'F', class_='type') tr.append(td1) href = fpath.basename if href_prefix: href = '%s%s' % (href_prefix, href) if fpath.check(dir=True): href += '/' td2 = html.td(html.a(fpath.basename, href=href), class_='name') tr.append(td2) td3 = html.td(time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(fpath.mtime())), class_='mtime') tr.append(td3) if fpath.check(dir=True): size = '' unit = '' else: size = fpath.size() unit = 'B' for u in ['kB', 'MB', 'GB', 'TB']: if size > 1024: size = round(size / 1024.0, 2) unit = u td4 = html.td('%s %s' % (size, unit), class_='size') tr.append(td4) return unicode(h)
def html_table_row(self): cells = html.tr([ html.td(v, class_=class_) for v, class_ in zip(self.formatted_statistics, COLUMN_CLASSES) ]) self.config.hook.pytest_aggreport_html_table_row(result=self, cells=cells) return cells
def make_table_rows(self, results): rv = [] for result in results: details_link = "%s/report.html" % result.name cells = [html.td(result.name)] if result.has_errors: cells.append(html.td( len(result.errors), class_="condition FAIL", )) else: cells.append(html.td("0", class_="condition PASS")) if result.has_regressions: num_regressions = sum(len(item) for item in result.regressions.itervalues()) cells.append(html.td(num_regressions, class_="condition FAIL")) else: cells.append(html.td("0", class_="condition PASS")) if result.is_pass: cells.append(html.td()) else: cells.append(html.td( html.a("details", href=details_link), class_="details" )) rv.append(html.tr(cells)) return rv
def make_errors_table(self, errors): rows = [] for error in errors: error_message = error.get("message", "") log = html.div(class_='log') for line in error_message.splitlines(): separator = line.startswith(' ' * 10) if separator: log.append(line[:80]) else: if line.lower().find("error") != -1 or line.lower().find("exception") != -1: log.append(html.span(raw(cgi.escape(line)), class_='error')) else: log.append(raw(cgi.escape(line))) log.append(html.br()) rows.append(html.tr( html.td(error["level"], class_="log_%s" % error["level"]), html.td(log, class_='log') )) return html.table(rows, id_="errors")
def _generate_environment(self, config): if not hasattr(config, '_metadata') or config._metadata is None: return [] metadata = config._metadata environment = [html.h2('Environment')] rows = [] keys = [k for k in metadata.keys() if metadata[k]] if not isinstance(metadata, OrderedDict): keys.sort() for key in keys: value = metadata[key] if isinstance(value, basestring) and value.startswith('http'): value = html.a(value, href=value, target='_blank') elif isinstance(value, (list, tuple, set)): value = ', '.join((str(i) for i in value)) rows.append(html.tr(html.td(key), html.td(value))) environment.append(html.table(rows, id='environment')) return environment
def generate_html(self): generated = datetime.utcnow() with open(os.path.join(base_path, "main.js")) as main_f: doc = html.html( self.head, html.body( html.script(raw(main_f.read())), html.p('Report generated on %s at %s' % ( generated.strftime('%d-%b-%Y'), generated.strftime('%H:%M:%S'))), html.h2('Environment'), html.table( [html.tr(html.td(k), html.td(v)) for k, v in sorted(self.env.items()) if v], id='environment'), html.h2('Summary'), html.p('%i tests ran in %.1f seconds.' % (sum(self.test_count.itervalues()), (self.suite_times["end"] - self.suite_times["start"]) / 1000.), html.br(), html.span('%i passed' % self.test_count["PASS"], class_='pass'), ', ', html.span('%i skipped' % self.test_count["SKIP"], class_='skip'), ', ', html.span('%i failed' % self.test_count["UNEXPECTED_FAIL"], class_='fail'), ', ', html.span('%i errors' % self.test_count["UNEXPECTED_ERROR"], class_='error'), '.', html.br(), html.span('%i expected failures' % self.test_count["EXPECTED_FAIL"], class_='expected_fail'), ', ', html.span('%i unexpected passes' % self.test_count["UNEXPECTED_PASS"], class_='unexpected_pass'), '.'), html.h2('Results'), html.table([html.thead( html.tr([ html.th('Result', class_='sortable', col='result'), html.th('Test', class_='sortable', col='name'), html.th('Duration', class_='sortable numeric', col='duration'), html.th('Links')]), id='results-table-head'), html.tbody(self.result_rows, id='results-table-body')], id='results-table'))) return u"<!DOCTYPE html>\n" + doc.unicode(indent=2)
def __init__(self, outcome, report, logfile, config): self.test_id = report.nodeid if getattr(report, 'when', 'call') != 'call': self.test_id = '::'.join([report.nodeid, report.when]) self.time = getattr(report, 'duration', 0.0) self.outcome = outcome self.additional_html = [] self.links_html = [] self.self_contained = config.getoption('self_contained_html') self.logfile = logfile self.config = config self.row_table = self.row_extra = None test_index = hasattr(report, 'rerun') and report.rerun + 1 or 0 for extra_index, extra in enumerate(getattr(report, 'extra', [])): self.append_extra_html(extra, extra_index, test_index) self.append_log_html(report, self.additional_html) cells = [ html.td(self.outcome, class_='col-result'), html.td(self.test_id, class_='col-name'), html.td('{0:.2f}'.format(self.time), class_='col-duration'), html.td(self.links_html, class_='col-links')] self.config.hook.pytest_html_results_table_row( report=report, cells=cells) self.config.hook.pytest_html_results_table_html( report=report, data=self.additional_html) if len(cells) > 0: self.row_table = html.tr(cells) self.row_extra = html.tr(html.td(self.additional_html, class_='extra', colspan=len(cells)))
def gen_html_table( mtx ): from py.xml import html # print("DBG genhtmltable", mtx) result = html.table( html.thead( html.tr( [html.th( x ) for x in mtx[0] ] ) ), # header html.tbody( *[ html.tr( [html.td( x ) for x in row] ) # rows for row in mtx[1:] ] ), class_="fixed_headers" ) # make it fixed height scrollable # https://codepen.io/tjvantoll/pen/JEKIu # result = str(result) + """ # """ return str(result)
def _extract_html(test, class_name, duration=0, text='', result='passed', debug=None): cls_name = class_name tc_name = unicode(test) tc_time = duration additional_html = [] debug = debug or {} links_html = [] if result in ['skipped', 'failure', 'expected failure', 'error']: if debug.get('screenshot'): screenshot = 'data:image/png;base64,%s' % debug['screenshot'] additional_html.append(html.div( html.a(html.img(src=screenshot), href="#"), class_='screenshot')) for name, content in debug.items(): try: if 'screenshot' in name: href = '#' else: # use base64 to avoid that some browser (such as Firefox, Opera) # treats '#' as the start of another link if the data URL contains. # use 'charset=utf-8' to show special characters like Chinese. href = 'data:text/plain;charset=utf-8;base64,%s' % base64.b64encode(content) links_html.append(html.a( name.title(), class_=name, href=href, target='_blank')) links_html.append(' ') except: pass log = html.div(class_='log') for line in text.splitlines(): separator = line.startswith(' ' * 10) if separator: log.append(line[:80]) else: if line.lower().find("error") != -1 or line.lower().find("exception") != -1: log.append(html.span(raw(cgi.escape(line)), class_='error')) else: log.append(raw(cgi.escape(line))) log.append(html.br()) additional_html.append(log) test_logs.append(html.tr([ html.td(result.title(), class_='col-result'), html.td(cls_name, class_='col-class'), html.td(tc_name, class_='col-name'), html.td(tc_time, class_='col-duration'), html.td(links_html, class_='col-links'), html.td(additional_html, class_='debug')], class_=result.lower() + ' results-table-row'))
def _extract_html(test, class_name, duration=0, text="", result="passed", debug=None): cls_name = class_name tc_name = unicode(test) tc_time = duration additional_html = [] debug = debug or {} links_html = [] if result in ["skipped", "failure", "expected failure", "error"]: if debug.get("screenshot"): screenshot = "data:image/png;base64,%s" % debug["screenshot"] additional_html.append(html.div(html.a(html.img(src=screenshot), href="#"), class_="screenshot")) for name, content in debug.items(): try: if "screenshot" in name: href = "#" else: # use base64 to avoid that some browser (such as Firefox, Opera) # treats '#' as the start of another link if the data URL contains. # use 'charset=utf-8' to show special characters like Chinese. href = "data:text/plain;charset=utf-8;base64,%s" % base64.b64encode(content) links_html.append(html.a(name.title(), class_=name, href=href, target="_blank")) links_html.append(" ") except: pass log = html.div(class_="log") for line in text.splitlines(): separator = line.startswith(" " * 10) if separator: log.append(line[:80]) else: if line.lower().find("error") != -1 or line.lower().find("exception") != -1: log.append(html.span(raw(cgi.escape(line)), class_="error")) else: log.append(raw(cgi.escape(line))) log.append(html.br()) additional_html.append(log) test_logs.append( html.tr( [ html.td(result.title(), class_="col-result"), html.td(cls_name, class_="col-class"), html.td(tc_name, class_="col-name"), html.td(tc_time, class_="col-duration"), html.td(links_html, class_="col-links"), html.td(additional_html, class_="debug"), ], class_=result.lower() + " results-table-row", ) )
def _appendrow(self, result, report): names = mangle_testnames(report.nodeid.split("::")) testclass = (names[:-1]) if self.prefix: testclass.insert(0, self.prefix) testclass = ".".join(testclass) testmethod = names[-1] time = getattr(report, 'duration', 0.0) additional_html = [] if not 'Passed' in result: if report.longrepr: log = html.div(class_='log') for line in str(report.longrepr).splitlines(): line = line.decode('utf8') separator = line.startswith('_ ' * 10) if separator: log.append(line[:80]) else: exception = line.startswith("E ") if exception: log.append(html.span(raw(cgi.escape(line)), class_='error')) else: log.append(raw(cgi.escape(line))) log.append(html.br()) if not os.path.exists(self.screenshot_path): os.makedirs(self.screenshot_path) self.append_screenshot(testmethod, log) additional_html.append(log) output = self._write_captured_output(report) info = output.split(" ") links_html = [] for i in range(0, len(info)): if ("http" in info[i] and "browserstack.com" in info[i]): links_html.append(html.a("link", href=info[i], target='_blank')) links_html.append(' ') self.test_logs.append(html.tr([ html.td(result, class_='col-result'), html.td(testclass, class_='col-class'), html.td(testmethod, class_='col-name'), html.td(round(time), class_='col-duration'), html.td(links_html, class_='col-links'), html.td(additional_html, class_='debug')], class_=result.lower() + ' results-table-row'))
def _appendrow(self, result, report): testclass = self.prefix + " " + self.current_test_info['package'] + self.current_test_info['class'] testmethod = self.current_test_info['name'] duration = getattr(report, 'duration', 0.0) additional_html = [] links_html = [] log = html.div(class_='log') if report.passed: log.append('Your tests are passing, but you are still curious. I like it :)') else: if hasattr(report, 'wasxfail'): self._append_xpass_section(log, report) if not report.skipped: self._append_crash_message_section(log, report) self._append_screenshot(testmethod, log) self._append_stacktrace_section(log, report) links_html.append(self._link_to_debug_event(testmethod, log)) output = self._append_captured_output(log, report) additional_html.append(log) links_html.append(self._link_to_browserstack_log(output)) self.test_logs.append(html.tr([ html.td(result, class_='col-result'), html.td(testclass, class_='col-class'), html.td(testmethod, class_='col-name'), html.td(round(duration), class_='col-duration'), html.td(links_html, class_='col-links'), html.td(additional_html, class_='debug')], class_=result.lower() + ' results-table-row'))
def make_table_rows(self, results): rv = [] for key in results.keys(): result = results[key]['results'] cells = [html.td(key, class_="col-subsuite")] if result.has_errors: cells.append(html.td( len(result.errors), class_="condition FAIL col-subsuite", )) else: cells.append(html.td("0", class_="condition PASS")) style = '' if result.has_fails or result.has_errors: style = 'background-color: darkblue;' if result.has_regressions: num_regressions = sum(len(item) for item in result.regressions.itervalues()) cells.append(html.td(num_regressions, class_="condition PASS", style=style)) else: cells.append(html.td("0", class_="condition PASS")) details_link = 'data:text/html;charset=utf-8;base64,%s' % base64.b64encode(results[key]['html_str']) ulbody = [html.li(html.a("subsuite report", href=details_link, target='_blank'))] files = results[key]['files'] for fname in files.keys(): href = '%s/%s' % (key, fname) #if key[-4:] == 'html' or key[-3:] == 'htm': # href = 'data:text/html;charset=utf-8;base64,%s' % base64.b64encode(files[key]) #else: # href = 'data:text/plain;charset=utf-8;base64,%s' % base64.b64encode(files[key]) ulbody.append(html.li(html.a(fname, href=href, target='_blank'))) cells.append(html.td(html.ul(ulbody), class_="details")) rv.append(html.tr(cells, class_='results-table-row')) return rv
def pytest_sessionfinish(self, session, exitstatus, __multicall__): self._make_report_dir() logfile = py.std.codecs.open(self.logfile, 'w', encoding='utf-8') suite_stop_time = time.time() suite_time_delta = suite_stop_time - self.suite_start_time numtests = self.passed + self.failed + self.xpassed + self.xfailed server = self.config.option.sauce_labs_credentials_file and \ 'Sauce Labs' or 'http://%s:%s' % (self.config.option.host, self.config.option.port) browser = self.config.option.browser_name and \ self.config.option.browser_version and \ self.config.option.platform and \ '%s %s on %s' % (str(self.config.option.browser_name).title(), self.config.option.browser_version, str(self.config.option.platform).title()) or \ self.config.option.environment or \ self.config.option.browser generated = datetime.datetime.now() configuration = { 'Base URL': self.config.option.base_url, 'Build': self.config.option.build, 'Selenium API': self.config.option.api, 'Driver': self.config.option.driver, 'Firefox Path': self.config.option.firefox_path, 'Google Chrome Path': self.config.option.chrome_path, 'Selenium Server': server, 'Browser': browser, 'Timeout': self.config.option.webqatimeout, 'Capture Network Traffic': self.config.option.capture_network, 'Credentials': self.config.option.credentials_file, 'Sauce Labs Credentials': self.config.option.sauce_labs_credentials_file} import pytest_mozwebqa doc = html.html( html.head( html.title('Test Report'), html.style( 'body {font-family: Helvetica, Arial, sans-serif; font-size: 12px}\n', 'body * {box-sizing: -moz-border-box; box-sizing: -webkit-border-box; box-sizing: border-box}\n', 'a {color: #999}\n', 'h2 {font-size: 16px}\n', 'table {border: 1px solid #e6e6e6; color: #999; font-size: 12px; border-collapse: collapse}\n', '#configuration tr:nth-child(odd) {background-color: #f6f6f6}\n', '#results {width:100%}\n', 'th, td {padding: 5px; border: 1px solid #E6E6E6; text-align: left}\n', 'th {font-weight: bold}\n', 'tr.passed, tr.skipped, tr.xfailed, tr.error, tr.failed, tr.xpassed {color: inherit}\n' 'tr.passed + tr.additional {display: none}\n', '.passed {color: green}\n', '.skipped, .xfailed {color: orange}\n', '.error, .failed, .xpassed {color: red}\n', '.log:only-child {height: inherit}\n', raw('.log {background-color: #e6e6e6; border: 1px solid #e6e6e6; color: black; display: block; font-family: "Courier New", Courier, monospace; height: 230px; overflow-y: scroll; padding: 5px; white-space:pre-wrap}\n'), '.screenshot, .video {border: 1px solid #e6e6e6; float:right; height:240px; margin-left:5px; overflow:hidden; width:320px}\n', '.screenshot img {width: 320px}')), html.body( html.p('Report generated on %s at %s by pytest-mozwebqa %s' % ( generated.strftime('%d-%b-%Y'), generated.strftime('%H:%M:%S'), pytest_mozwebqa.__version__)), html.h2('Configuration'), html.table( [html.tr(html.td(k), html.td(v)) for k, v in sorted(configuration.items()) if v], id='configuration'), html.h2('Summary'), html.p( '%i tests ran in %i seconds.' % (numtests, suite_time_delta), html.br(), html.span('%i passed' % self.passed, class_='passed'), ', ', html.span('%i skipped' % self.skipped, class_='skipped'), ', ', html.span('%i failed' % self.failed, class_='failed'), ', ', html.span('%i errors' % self.errors, class_='error'), '.', html.br(), html.span('%i expected failures' % self.xfailed, class_='skipped'), ', ', html.span('%i unexpected passes' % self.xpassed, class_='failed'), '.'), html.h2('Results'), html.table( html.tr(html.th('Result'), html.th('Class'), html.th('Name'), html.th('Duration'), html.th('Links')), *self.test_logs, id='results'))) logfile.write(doc.unicode(indent=2)) logfile.close()
def indexroot(self, user, index): stage = self.getstage(user, index) if json_preferred(): projectlist = stage.getprojectnames_perstage() projectlist = sorted(projectlist) apireturn(200, type="list:projectconfig", result=projectlist) if stage.name == "root/pypi": return simple_html_body("%s index" % stage.name, [ html.ul( html.li(html.a("simple index", href="+simple/")), ), ]).unicode() # XXX this should go to a template if hasattr(stage, "ixconfig"): bases = html.ul() for base in stage.ixconfig["bases"]: bases.append(html.li( html.a("%s" % base, href="/%s/" % base), " (", html.a("simple", href="/%s/+simple/" % base), " )", )) if bases: bases = [html.h2("inherited bases"), bases] else: bases = [] latest_packages = html.table( html.tr(html.td("info"), html.td("file"), html.td("docs"))) for projectname in stage.getprojectnames_perstage(): metadata = stage.get_metadata_latest(projectname) try: name, ver = metadata["name"], metadata["version"] except KeyError: log.error("metadata for project %r empty: %s, skipping", projectname, metadata) continue dockey = stage._doc_key(name, ver) if dockey.exists(): docs = [html.a("%s-%s docs" %(name, ver), href="%s/%s/+doc/index.html" %(name, ver))] else: docs = [] files = metadata.get("+files", {}) if not files: log.warn("project %r version %r has no files", projectname, metadata.get("version")) baseurl = URL(request.path) for basename, relpath in files.items(): latest_packages.append(html.tr( html.td(html.a("%s-%s info page" % (name, ver), href="%s/%s/" % (name, ver))), html.td(html.a(basename, href=baseurl.relpath("/" + relpath))), html.td(*docs), )) break # could present more releasefiles latest_packages = [ html.h2("in-stage latest packages, at least as recent as bases"), latest_packages] return simple_html_body("%s index" % stage.name, [ html.ul( html.li(html.a("simple index", href="+simple/")), ), latest_packages, bases, ]).unicode()
def pytest_sessionfinish(self, session, exitstatus, __multicall__): self._make_report_dir() logfile = py.std.codecs.open(self.logfile, 'w', encoding='utf-8') suite_stop_time = time.time() suite_time_delta = suite_stop_time - self.suite_start_time numtests = self.passed + self.failed + self.xpassed + self.xfailed server = self.config.option.sauce_labs_credentials_file and \ 'Sauce Labs' or 'http://%s:%s' % (self.config.option.host, self.config.option.port) browser = self.config.option.browser_name and \ self.config.option.browser_version and \ self.config.option.platform and \ '%s %s on %s' % (str(self.config.option.browser_name).title(), self.config.option.browser_version, str(self.config.option.platform).title()) or \ self.config.option.environment or \ self.config.option.browser generated = datetime.datetime.now() configuration = { 'Base URL': self.config.option.base_url, 'Build': self.config.option.build, 'Selenium API': self.config.option.api, 'Driver': self.config.option.driver, 'Firefox Path': self.config.option.firefox_path, 'Google Chrome Path': self.config.option.chrome_path, 'Selenium Server': server, 'Browser': browser, 'Timeout': self.config.option.webqatimeout, 'Capture Network Traffic': self.config.option.capture_network, 'Credentials': self.config.option.credentials_file, 'Sauce Labs Credentials': self.config.option.sauce_labs_credentials_file} import pytest_mozwebqa doc = html.html( html.head( html.meta(charset='utf-8'), html.title('Test Report'), html.link(rel='stylesheet', href='style.css'), html.script(src='jquery.js'), html.script(src='main.js')), html.body( html.p('Report generated on %s at %s by pytest-mozwebqa %s' % ( generated.strftime('%d-%b-%Y'), generated.strftime('%H:%M:%S'), pytest_mozwebqa.__version__)), html.h2('Configuration'), html.table( [html.tr(html.td(k), html.td(v)) for k, v in sorted(configuration.items()) if v], id='configuration'), html.h2('Summary'), html.p( '%i tests ran in %i seconds.' % (numtests, suite_time_delta), html.br(), html.span('%i passed' % self.passed, class_='passed'), ', ', html.span('%i skipped' % self.skipped, class_='skipped'), ', ', html.span('%i failed' % self.failed, class_='failed'), ', ', html.span('%i errors' % self.errors, class_='error'), '.', html.br(), html.span('%i expected failures' % self.xfailed, class_='skipped'), ', ', html.span('%i unexpected passes' % self.xpassed, class_='failed'), '.'), html.h2('Results'), html.table([ html.thead(html.tr([ html.th('Result', class_='sortable', col='result'), html.th('Class', class_='sortable', col='class'), html.th('Name', class_='sortable', col='name'), html.th('Duration', class_='sortable numeric', col='duration'), html.th('Links')]), id='results-table-head'), html.tbody(*self.test_logs, id='results-table-body')], id='results-table'))) logfile.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' + doc.unicode(indent=2)) logfile.close()
def _appendrow(self, result, report): import pytest_mozwebqa (testclass, testmethod) = pytest_mozwebqa.split_class_and_test_names(report.nodeid) time = getattr(report, 'duration', 0.0) links = {} if hasattr(report, 'debug') and any(report.debug.values()): (relative_path, full_path) = self._debug_paths(testclass, testmethod) if report.debug['screenshots']: filename = 'screenshot.png' f = open(os.path.join(full_path, filename), 'wb') f.write(base64.decodestring(report.debug['screenshots'][-1])) links.update({'Screenshot': os.path.join(relative_path, filename)}) if report.debug['html']: filename = 'html.txt' f = open(os.path.join(full_path, filename), 'wb') f.write(report.debug['html'][-1]) links.update({'HTML': os.path.join(relative_path, filename)}) # Log may contain passwords, etc so we only capture it for tests marked as public if report.debug['logs'] and 'public' in report.keywords: filename = 'log.txt' f = open(os.path.join(full_path, filename), 'wb') f.write(report.debug['logs'][-1]) links.update({'Log': os.path.join(relative_path, filename)}) if report.debug['network_traffic']: filename = 'networktraffic.json' f = open(os.path.join(full_path, filename), 'wb') f.write(report.debug['network_traffic'][-1]) links.update({'Network Traffic': os.path.join(relative_path, filename)}) if report.debug['urls']: links.update({'Failing URL': report.debug['urls'][-1]}) if self.config.option.sauce_labs_credentials_file and hasattr(report, 'session_id'): self.sauce_labs_job = sauce_labs.Job(report.session_id) if hasattr(self, 'sauce_labs_job'): links['Sauce Labs Job'] = self.sauce_labs_job.url links_html = [] for name, path in links.iteritems(): links_html.append(html.a(name, href=path)) links_html.append(' ') additional_html = [] if not 'Passed' in result: if hasattr(self, 'sauce_labs_job'): additional_html.append(self.sauce_labs_job.video_html) if 'Screenshot' in links: additional_html.append( html.div( html.a(html.img(src=links['Screenshot']), href=links['Screenshot']), class_='screenshot')) if report.longrepr: log = html.div(class_='log') for line in str(report.longrepr).splitlines(): separator = line.startswith('_ ' * 10) if separator: log.append(line[:80]) else: exception = line.startswith("E ") if exception: log.append(html.span(raw(cgi.escape(line)), class_='error')) else: log.append(raw(cgi.escape(line))) log.append(html.br()) additional_html.append(log) self.test_logs.append(html.tr([ html.td(result, class_='col-result'), html.td(testclass, class_='col-class'), html.td(testmethod, class_='col-name'), html.td(round(time), class_='col-duration'), html.td(links_html, class_='col-links'), html.td(additional_html, class_='debug')], class_=result.lower() + ' results-table-row'))
def _appendrow(self, result, report): time = getattr(report, 'duration', 0.0) additional_html = [] links_html = [] for extra in getattr(report, 'extra', []): href = None if extra.get('format') == extras.FORMAT_IMAGE: href = '#' image = 'data:image/png;base64,{0}'.format( extra.get('content')) additional_html.append(html.div( html.a(html.img(src=image), href="#"), class_='image')) elif extra.get('format') == extras.FORMAT_HTML: additional_html.append(html.div(raw(extra.get('content')))) elif extra.get('format') == extras.FORMAT_JSON: href = data_uri(json.dumps(extra.get('content')), mime_type='application/json') elif extra.get('format') == extras.FORMAT_TEXT: href = data_uri(extra.get('content')) elif extra.get('format') == extras.FORMAT_URL: href = extra.get('content') if href is not None: links_html.append(html.a( extra.get('name'), class_=extra.get('format'), href=href, target='_blank')) links_html.append(' ') if report.longrepr: log = html.div(class_='log') for line in str(report.longrepr).splitlines(): if not PY3: line = line.decode('utf-8') separator = line.startswith('_ ' * 10) if separator: log.append(line[:80]) else: exception = line.startswith("E ") if exception: log.append(html.span(raw(escape(line)), class_='error')) else: log.append(raw(escape(line))) log.append(html.br()) for header, content in report.sections: log.append(' {0} '.format(header).center(80, '-')) log.append(html.br()) log.append(content) else: log = html.div(class_='empty log') log.append('No log output captured.') additional_html.append(log) test_id = report.nodeid if report.when != 'call': test_id = '::'.join([report.nodeid, report.when]) self.test_logs.append(html.tr([ html.td(result, class_='col-result'), html.td(test_id, class_='col-name'), html.td('{0:.2f}'.format(time), class_='col-duration'), html.td(links_html, class_='col-links'), html.td(additional_html, class_='extra')], class_=result.lower() + ' results-table-row'))
def pytest_sessionfinish(self, session): if not os.path.exists(os.path.dirname(self.logfile)): os.makedirs(os.path.dirname(self.logfile)) logfile = open(self.logfile, 'w', encoding='utf-8') suite_stop_time = time.time() suite_time_delta = suite_stop_time - self.suite_start_time numtests = self.passed + self.failed + self.xpassed + self.xfailed generated = datetime.datetime.now() style_css = pkg_resources.resource_string( __name__, os.path.join('resources', 'style.css')) if PY3: style_css = style_css.decode('utf-8') head = html.head( html.meta(charset='utf-8'), html.title('Test Report'), html.style(raw(style_css))) summary = [html.h2('Summary'), html.p( '{0} tests ran in {1:.2f} seconds.'.format( numtests, suite_time_delta), html.br(), html.span('{0} passed'.format( self.passed), class_='passed'), ', ', html.span('{0} skipped'.format( self.skipped), class_='skipped'), ', ', html.span('{0} failed'.format( self.failed), class_='failed'), ', ', html.span('{0} errors'.format( self.errors), class_='error'), '.', html.br(), html.span('{0} expected failures'.format( self.xfailed), class_='skipped'), ', ', html.span('{0} unexpected passes'.format( self.xpassed), class_='failed'), '.')] results = [html.h2('Results'), html.table([html.thead( html.tr([ html.th('Result', class_='sortable initial-sort result', col='result'), html.th('Test', class_='sortable', col='name'), html.th('Duration', class_='sortable numeric', col='duration'), html.th('Links')]), id='results-table-head'), html.tbody(*self.test_logs, id='results-table-body')], id='results-table')] main_js = pkg_resources.resource_string( __name__, os.path.join('resources', 'main.js')) if PY3: main_js = main_js.decode('utf-8') body = html.body( html.script(raw(main_js)), html.p('Report generated on {0} at {1}'.format( generated.strftime('%d-%b-%Y'), generated.strftime('%H:%M:%S')))) if session.config._environment: environment = set(session.config._environment) body.append(html.h2('Environment')) body.append(html.table( [html.tr(html.td(e[0]), html.td(e[1])) for e in sorted( environment, key=lambda e: e[0]) if e[1]], id='environment')) body.extend(summary) body.extend(results) doc = html.html(head, body) logfile.write('<!DOCTYPE html>') unicode_doc = doc.unicode(indent=2) if PY3: # Fix encoding issues, e.g. with surrogates unicode_doc = unicode_doc.encode('utf-8', errors='xmlcharrefreplace') unicode_doc = unicode_doc.decode('utf-8') logfile.write(unicode_doc) logfile.close()