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 append_log_html(self, report, additional_html): log = html.div(class_='log') if report.longrepr: 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 section in report.sections: header, content = map(escape, section) log.append(' {0} '.format(header).center(80, '-')) log.append(html.br()) if ANSI: converter = Ansi2HTMLConverter(inline=False, escaped=False) content = converter.convert(content, full=False) log.append(raw(content)) if len(log) == 0: log = html.div(class_='empty log') log.append('No log output captured.') additional_html.append(log)
def insert_data(self, tables_data: dict): if not isinstance(tables_data, dict): raise TypeError( f'{self.__module__} supports only dict as InputParam') self.tables_processed = len(tables_data.keys()) for raw_table_name, raw_table_data in tables_data.items(): csv_file_path = raw_table_data['Athena']['FilePath'] database_name, table_name = raw_table_name.split('.') self.data_results.append( html.div( html.h3(f"Input data: {raw_table_name}"), html.table( html.tr([ html.th('Database:', class_='database-name'), html.th(database_name) ]), html.tr([ html.th('Table name:', class_='table-name'), html.th(table_name) ]), self._generate_glue_report(raw_table_data['Glue']), self._generate_s3_report(raw_table_data['S3']), self._generate_athena_report(raw_table_data['Athena']), class_="processed-table"), html.div(f"{self._get_csv_data(csv_file_path)}", table_name=table_name, class_="data-tables")))
def append_log_html(self, report, additional_html): log = html.div(class_='log') if report.longrepr: for line in report.longreprtext.splitlines(): 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 section in report.sections: header, content = map(escape, section) log.append(' {0} '.format(header).center(80, '-')) log.append(html.br()) if ANSI: converter = Ansi2HTMLConverter(inline=False, escaped=False) content = converter.convert(content, full=False) log.append(raw(content)) if len(log) == 0: log = html.div(class_='empty log') log.append('No log output captured.') additional_html.append(log)
def append_log_html(self, report, additional_html): log = html.div(class_="log") if report.longrepr: for line in report.longreprtext.splitlines(): 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 section in report.sections: header, content = map(escape, section) log.append(f" {header:-^80} ") log.append(html.br()) if ANSI: converter = Ansi2HTMLConverter(inline=False, escaped=False) content = converter.convert(content, full=False) log.append(raw(content)) log.append(html.br()) if len(log) == 0: log = html.div(class_="empty log") log.append("No log output captured.") additional_html.append(log)
def append_log_html(self, report, additional_html): log = html.div(class_='log') if report.longrepr: 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) if len(log) == 0: log = html.div(class_='empty log') log.append('No log output captured.') additional_html.append(log)
def append_extra_html(self, extra, additional_html, links_html): 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(' ')
def append_log_html(self, report, additional_html): log = html.div(class_='log') if report.longrepr: for line in report.longreprtext.splitlines(): 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 section in report.sections: #header, content = map(escape, section) header = section[0] content = escape(section[1].replace("\\","\\\\")) #print('header1 : ',header) #print('content1 : ',content) log.append(' {0} '.format(header).center(80, '-')) log.append(html.br()) if ANSI: converter = Ansi2HTMLConverter(inline=False, escaped=False) content = converter.convert(content, full=False) log.append(raw(content)) if len(log) == 0: log = html.div(class_='empty log') log.append('No log output captured.') additional_html.append(log)
def _create_run_divs(self, run, run_error, single_run): # Create run main div run_main_div = html.div(class_="run_main", count=run) # Create run label div run_label_div = html.div("Run {run} {pass_or_fail}".format( run=run, pass_or_fail="failed" if run_error else "passed"), html.span(" (show/hide)", class_="hint"), class_="run_label", count=run) # Create run content div run_content_div = html.div(class_="run_content", count=run) # If more than one run collapse the run divs if not single_run: run_content_div.attr.__setattr__("style", "display:none") # Add success attribute if run_error: run_label_div.attr.__setattr__("success", "false") run_content_div.attr.__setattr__("success", "false") run_main_div.attr.__setattr__("success", "false") self._append_run_error(run_content_div, run_error=run_error) else: run_label_div.attr.__setattr__("success", "true") run_content_div.attr.__setattr__("success", "true") run_main_div.attr.__setattr__("success", "true") run_main_div.append(run_label_div) run_main_div.append(run_content_div) return run_main_div, run_content_div
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 append_extra_html(self, extra, extra_index, test_index): href = None if extra.get('format') == extras.FORMAT_IMAGE: content = extra.get('content') if content.startswith(('file', 'http')) or \ os.path.isfile(content): if self.self_contained: warnings.warn('Self-contained HTML report ' 'includes link to external ' 'resource: {}'.format(content)) html_div = html.a(html.img(src=content), href=content) elif self.self_contained: src = 'data:{0};base64,{1}'.format(extra.get('mime_type'), content) html_div = html.img(src=src) else: if PY3: content = b64decode(content.encode('utf-8')) else: content = b64decode(content) href = src = self.create_asset(content, extra_index, test_index, extra.get('extension'), 'wb') html_div = html.a(html.img(src=src), href=href) self.additional_html.append(html.div(html_div, class_='image')) elif extra.get('format') == extras.FORMAT_HTML: self.additional_html.append(html.div(raw( extra.get('content')))) elif extra.get('format') == extras.FORMAT_JSON: content = json.dumps(extra.get('content')) if self.self_contained: href = data_uri(content, mime_type=extra.get('mime_type')) else: href = self.create_asset(content, extra_index, test_index, extra.get('extension')) elif extra.get('format') == extras.FORMAT_TEXT: content = extra.get('content') if self.self_contained: href = data_uri(content) else: href = self.create_asset(content, extra_index, test_index, extra.get('extension')) elif extra.get('format') == extras.FORMAT_URL: href = extra.get('content') if href is not None: self.links_html.append( html.a(extra.get('name'), class_=extra.get('format'), href=href, target='_blank')) self.links_html.append(' ')
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 _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 append_extra_html(self, extra, extra_index, test_index): href = None if extra.get('format') == extras.FORMAT_IMAGE: if self.self_contained: src = 'data:{0};base64,{1}'.format(extra.get('mime_type'), extra.get('content')) self.additional_html.append( html.div(html.img(src=src), class_='image')) else: content = extra.get('content') if PY3: content = b64decode(content.encode('utf-8')) else: content = b64decode(content) href = src = self.create_asset(content, extra_index, test_index, extra.get('extension'), 'wb') self.additional_html.append( html.div(html.a(html.img(src=src), href=href), class_='image')) elif extra.get('format') == extras.FORMAT_HTML: self.additional_html.append(html.div(raw( extra.get('content')))) elif extra.get('format') == extras.FORMAT_JSON: content = json.dumps(extra.get('content')) if self.self_contained: href = data_uri(content, mime_type=extra.get('mime_type')) else: href = self.create_asset(content, extra_index, test_index, extra.get('extension')) elif extra.get('format') == extras.FORMAT_TEXT: content = extra.get('content') if self.self_contained: href = data_uri(content) else: href = self.create_asset(content, extra_index, test_index, extra.get('extension')) elif extra.get('format') == extras.FORMAT_URL: href = extra.get('content') if href is not None: self.links_html.append( html.a(extra.get('name'), class_=extra.get('format'), href=href, target='_blank')) self.links_html.append(' ')
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 pytest_sessionfinish(self, session, exitstatus): 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 generated = datetime.datetime.now() 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 ' % ( generated.strftime('%d-%b-%Y'), generated.strftime('%H:%M:%S'), )), html.div([html.p( html.span('%i tests' % numtests, class_='all clickable'), ' ran in %i seconds.' % suite_time_delta, html.br(), html.span('%i passed' % self.passed, class_='passed clickable'), ', ', html.span('%i skipped' % self.skipped, class_='skipped clickable'), ', ', html.span('%i failed' % self.failed, class_='failed clickable'), ', ', html.span('%i errors' % self.errors, class_='error clickable'), '.', html.br(), ), html.span('Hide all errors', class_='clickable hide_all_errors'), ', ', html.span('Show all errors', class_='clickable show_all_errors'), ], id='summary-wrapper'), html.div(id='summary-space'), 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('Output')]), id='results-table-head'), 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() self.process_screenshot_files() self.process_debug_event_files() self.process_performance_files()
def append_log_html( self, report, additional_html, pytest_show_capture_value, ): log = html.div(class_="log") self._populate_html_log_div(log, report, pytest_show_capture_value) if len(log) == 0: log = html.div(class_="empty log") log.append("No log output captured.") additional_html.append(log)
def pytest_html_results_table_html(report, data): if report.failed: # Extract important lines failure_lines = [ line for line in lxmlhtml.fromstring(str(data[-1])).xpath( '//div/text()') if line.startswith(">") or " def " in line ] error_spans = [ str(html.span("* " + line[1:].lstrip().rstrip(), class_='error')) for line in lxmlhtml.fromstring( str(data[-1])).xpath('//span/text()') if "Fail Message(s) for test" not in line ] # Reconstruct error log # Taken from append_log_html in https://github.com/pytest-dev/pytest-html/blob/master/pytest_html/plugin.py del data[-1] log = html.div(class_='log') for line in failure_lines: log.append(raw(line)) log.append(html.br()) for line in error_spans: log.append(html.span(raw(line), class_='error')) log.append(html.br()) data.append(log) elif report.passed: del data[1]
def _generate_html(pages): """Generate html for given pages. :param pages: list of `Page.class` :return: path to tempdir. :rtype: string. """ tempdir = tempfile.mkdtemp() doc = html.html( html.head( # python don't allow keyword args with hypens html.meta(content="text/html; charset=utf-8", **{"http-equiv": "Content-Type"}), _get_tile(html, pages) ), html.body( html.div(_generate_body(html, pages, tempdir), id='article'), ) ) with open(os.path.join(tempdir, 'histmag.html'), 'wb') as out_file: logger.debug( 'Saving generated html to {file}'.format(file=os.path.join(tempdir, 'histmag.html')) ) out_file.write(doc.unicode(indent=2).encode('utf8')) return tempdir
def startDocument(self): super(PageHandler, self).startDocument() self.head.append(html.link(type='text/css', rel='stylesheet', href='style.css')) title = self.title[0] breadcrumb = ''.join([unicode(el) for el in self.breadcrumb(title)]) self.body.append(html.div(raw(breadcrumb), class_='breadcrumb'))
def _append_run_error(self, div, run_error): run_error_div = html.div(class_="run_error") self._append_exception_section(run_error_div, run_error) div.append(run_error_div) div.append(html.br())
def pytest_html_results_table_html(report, data): """去掉默认的日志捕获,只要异常说明""" # 这个没找到好的办法,自从吧pytest和pytest-html升级之后报告中输出的日志就变多了, # 以前只有Captured log call这一部分来着,现在没找到好办法解决,现在这个办法只是乱搞 tt = data[0] stt = '------------------------------Captured' slog = 'Captured log call' slog_n = -3 for i in range(len(tt)): if isinstance(tt[i], str): if slog in tt[i]: slog_n = i break for i in range(len(tt)): if isinstance(tt[i], str): if stt in tt[i]: del tt[i:slog_n] break del data[:] if report.passed: data.append(html.div("No log output captured.", class_="empty log")) else: # # failtext = [x for x in report.longreprtext.split('\n')] # # fail_p = report.longreprtext # fail_p = '<br/>'.join(qq) # data.append(html.div(fail_p, class_="failed log")) data.append(tt)
def pytest_runtest_makereport(__multicall__, item): report = __multicall__.execute() extra = getattr(report, 'extra', []) if report.when == 'call': desc = item.get_marker("desc") if desc is not None: for info in desc: if (info.args[0] and info.args[0] != ""): extra.append(extras.html(html.div(info.args[0]))) xfail = item.get_marker("xfail") if xfail is not None: for info in xfail: if info.kwargs and 'buglink' in info.kwargs: extra.append(extras.url(info.kwargs['buglink'])) skipif = item.get_marker("skipif") if skipif is not None: for info in skipif: if info.kwargs and 'buglink' in info.kwargs: extra.append(extras.url(info.kwargs['buglink'])) report.extra = extra return report
def _create_request_headers_divs(self, request_headers): # Create request headers main div request_headers_main_div = html.div(class_="request_headers_main") # Create request headers show/hide div request_headers_label_div = html.div( html.span("show/hide headers", class_="hint"), class_="request_headers_label") # Create request headers content div request_headers_content_div = html.div( raw(request_headers), class_="request_headers_content", style="display:none") request_headers_main_div.append(request_headers_label_div) request_headers_main_div.append(request_headers_content_div) return request_headers_main_div
def _create_be_stack_trace_divs(self, be_stack_trace): # Create be stack trace main div be_stack_trace_main_div = html.div(class_="be_stack_trace_main") # Create be stack trace show/hide div be_stack_trace_label_div = html.div("Backend stack trace", html.span(" (show/hide)", class_="hint"), class_="be_stack_trace_label") # Create be stack trace content div be_stack_trace_content_div = html.div( raw(be_stack_trace), class_="be_stack_trace_content", style="display:none") be_stack_trace_main_div.append(be_stack_trace_label_div) be_stack_trace_main_div.append(be_stack_trace_content_div) return be_stack_trace_main_div
def _create_test_debug_logs_divs(self, test_debug_logs): # Create test debug logs main div test_debug_logs_main_div = html.div(class_="test_debug_logs_main") # Create test debug logs show/hide div test_debug_logs_label_div = html.div( "Test debug logs", html.span(" (show/hide)", class_="hint"), class_="test_debug_logs_label") # Create test debug logs content div test_debug_logs_content_div = html.div( test_debug_logs, class_="test_debug_logs_content", style="display:none") test_debug_logs_main_div.append(test_debug_logs_label_div) test_debug_logs_main_div.append(test_debug_logs_content_div) return test_debug_logs_main_div
def make_body(self): body_parts = [html.div( html.h1("FirefoxOS Certification Suite Report"), html.p("Run at %s" % self.time.strftime("%Y-%m-%d %H:%M:%S")) )] 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(self.make_result_table()) return html.body(body_parts)
def _create_test_step_divs(self, step_name, step_log): # Create test step main div test_step_main_div = html.div(class_="test_step_main") # Create test step show/hide div test_step_label_div = html.div(step_name, html.span(" (show/hide)", class_="hint"), class_="test_step_label", name=step_name) # Create test step content div test_step_content_div = html.div(raw(step_log), class_="test_step_content", name=step_name, style="display:none") test_step_main_div.append(test_step_label_div) test_step_main_div.append(test_step_content_div) return test_step_main_div
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 append_log_html( self, report, additional_html, pytest_capture_value, pytest_show_capture_value, ): log = html.div(class_="log") should_skip_captured_output = pytest_capture_value == "no" if report.outcome == "failed" and not should_skip_captured_output: should_skip_captured_output = pytest_show_capture_value == "no" if not should_skip_captured_output: self._populate_html_log_div(log, report) if len(log) == 0: log = html.div(class_="empty log") log.append("No log output captured.") additional_html.append(log)
def __init__(self, html_file=None, contextual_differences=True): super(HTMLDiffHelper, self).__init__() # init logger self.logger = logging.getLogger(__name__) # setup the html_file if html_file is None: self.html_file = 'diff.html' else: self.html_file = html_file # loading the html settings self.div_container = html.div(class_='container') self.contextual_differences = contextual_differences
def append_log_html(self, report, additional_html): log = html.div(class_="log") if report.longrepr: # longreprtext is only filled out on failure by pytest # otherwise will be None. # Use full_text if longreprtext is None-ish # we added full_text elsewhere in this file. text = report.longreprtext or report.full_text for line in text.splitlines(): 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 section in report.sections: header, content = map(escape, section) log.append(f" {header:-^80} ") log.append(html.br()) if ansi_support(): converter = ansi_support().Ansi2HTMLConverter( inline=False, escaped=False) content = converter.convert(content, full=False) else: content = _remove_ansi_escape_sequences(content) log.append(raw(content)) log.append(html.br()) if len(log) == 0: log = html.div(class_="empty log") log.append("No log output captured.") additional_html.append(log)
def _video_html(video_url, session): return str( html.div( html.video( html.source(src=video_url, type="video/mp4"), width="100%", height="100%", controls="controls", ), id="mediaplayer{session}".format(session=session), style="border:1px solid #e6e6e6; float:right; height:240px;" "margin-left:5px; overflow:hidden; width:320px", ))
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 _video_html(session): flash_vars = 'config={{\ "clip":{{\ "url":"https://assets.saucelabs.com/jobs/{session}/video.flv",\ "provider":"streamer",\ "autoPlay":false,\ "autoBuffering":true}},\ "play": {{\ "opacity":1,\ "label":null,\ "replayLabel":null}},\ "plugins":{{\ "streamer":{{\ "url":"https://cdn1.saucelabs.com/sauce_skin_deprecated\ /lib/flowplayer/flowplayer.pseudostreaming-3.2.13.swf",\ "queryString":"%%3Fstart%%3D%%24%%7Bstart%%7D"}},\ "controls":{{\ "mute":false,\ "volume":false,\ "backgroundColor":"rgba(0,0,0,0.7)"}}}},\ "playerId":"player{session}",\ "playlist":[{{\ "url":"https://assets.saucelabs.com/jobs/{session}/video.flv",\ "provider":"streamer",\ "autoPlay":false,\ "autoBuffering":true}}]}}'.format( session=session ) return str( html.div( html.object( html.param(value="true", name="allowfullscreen"), html.param(value="always", name="allowscriptaccess"), html.param(value="high", name="quality"), html.param(value="#000000", name="bgcolor"), html.param(value=flash_vars.replace(" ", ""), name="flashvars"), width="100%", height="100%", type="application/x-shockwave-flash", data="https://cdn1.saucelabs.com/sauce_skin_deprecated/lib/" "flowplayer/flowplayer-3.2.17.swf", name="player_api", id="player_api", ), id="player{session}".format(session=session), style="border:1px solid #e6e6e6; float:right; height:240px;" "margin-left:5px; overflow:hidden; width:320px", ) )
def _video_html(video_url, session): return str( html.div( html.video( html.source(src=video_url, type="video/mp4"), width="100%", height="100%", controls="controls", ), id="mediaplayer{session}".format(session=session), style="border:1px solid #e6e6e6; float:right; height:240px;" "margin-left:5px; overflow:hidden; width:320px", ) )
def _get_log_from_report(self, report): log = html.div(class_='log') if report.longrepr: for line in report.longreprtext.splitlines(): 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 section in report.sections: header, content = map(escape, section) log.append(' {0} '.format(header).center(80, '-')) log.append(html.br()) if ANSI: converter = Ansi2HTMLConverter(inline=False, escaped=False) content = converter.convert(content, full=False) log.append(raw(content)) if len(log) == 0: log = html.div(class_='empty log') log.append('No log output captured.') unicode_log = log.unicode(indent=2) if PY3: # Fix encoding issues, e.g. with surrogates unicode_log = unicode_log.encode('utf-8', errors='xmlcharrefreplace') unicode_log = unicode_log.decode('utf-8') return unicode_log
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 _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 _video_html(self, session): flash_vars = 'config={{\ "clip":{{\ "url":"https://assets.saucelabs.com/jobs/{0}/video.flv",\ "provider":"streamer",\ "autoPlay":false,\ "autoBuffering":true}},\ "play": {{\ "opacity":1,\ "label":null,\ "replayLabel":null}},\ "plugins":{{\ "streamer":{{\ "url":"https://cdn1.saucelabs.com/sauce_skin_deprecated\ /lib/flowplayer/flowplayer.pseudostreaming-3.2.13.swf",\ "queryString":"%%3Fstart%%3D%%24%%7Bstart%%7D"}},\ "controls":{{\ "mute":false,\ "volume":false,\ "backgroundColor":"rgba(0,0,0,0.7)"}}}},\ "playerId":"player{0}",\ "playlist":[{{\ "url":"https://assets.saucelabs.com/jobs/{0}/video.flv",\ "provider":"streamer",\ "autoPlay":false,\ "autoBuffering":true}}]}}'.format(session) return str(html.div(html.object( html.param(value='true', name='allowfullscreen'), html.param(value='always', name='allowscriptaccess'), html.param(value='high', name='quality'), html.param(value='#000000', name='bgcolor'), html.param( value=flash_vars.replace(' ', ''), name='flashvars'), width='100%', height='100%', type='application/x-shockwave-flash', data='https://cdn1.saucelabs.com/sauce_skin_deprecated/lib/' 'flowplayer/flowplayer-3.2.17.swf', name='player_api', id='player_api'), id='player{0}'.format(session), style='border:1px solid #e6e6e6; float:right; height:240px;' 'margin-left:5px; overflow:hidden; width:320px'))
def append_extra_html(self, extra, extra_index, test_index): href = None if extra.get("format") == extras.FORMAT_IMAGE: self._append_image(extra, extra_index, test_index) elif extra.get("format") == extras.FORMAT_HTML: self.additional_html.append(html.div(raw(extra.get("content")))) elif extra.get("format") == extras.FORMAT_JSON: content = json.dumps(extra.get("content")) if self.self_contained: href = data_uri(content, mime_type=extra.get("mime_type")) else: href = self.create_asset( content, extra_index, test_index, extra.get("extension") ) elif extra.get("format") == extras.FORMAT_TEXT: content = extra.get("content") if isinstance(content, bytes): content = content.decode("utf-8") if self.self_contained: href = data_uri(content) else: href = self.create_asset( content, extra_index, test_index, extra.get("extension") ) elif extra.get("format") == extras.FORMAT_URL: href = extra.get("content") elif extra.get("format") == extras.FORMAT_VIDEO: self._append_video(extra, extra_index, test_index) if href is not None: self.links_html.append( html.a( extra.get("name"), class_=extra.get("format"), href=href, target="_blank", ) ) self.links_html.append(" ")
def _video_html(self, session): flash_vars = 'config={\ "clip":{\ "url":"https://assets.saucelabs.com/jobs/%(session)s/video.flv",\ "provider":"streamer",\ "autoPlay":false,\ "autoBuffering":true},\ "play": {\ "opacity":1,\ "label":null,\ "replayLabel":null},\ "plugins":{\ "streamer":{\ "url":"https://cdn1.saucelabs.com/sauce_skin_deprecated/lib/flowplayer/flowplayer.pseudostreaming-3.2.13.swf",\ "queryString":"%%3Fstart%%3D%%24%%7Bstart%%7D"},\ "controls":{\ "mute":false,\ "volume":false,\ "backgroundColor":"rgba(0,0,0,0.7)"}},\ "playerId":"player%(session)s",\ "playlist":[{\ "url":"https://assets.saucelabs.com/jobs/%(session)s/video.flv",\ "provider":"streamer",\ "autoPlay":false,\ "autoBuffering":true}]}' % {'session': session} return html.div(html.object( html.param(value='true', name='allowfullscreen'), html.param(value='always', name='allowscriptaccess'), html.param(value='high', name='quality'), html.param(value='#000000', name='bgcolor'), html.param( value=flash_vars.replace(' ', ''), name='flashvars'), width='100%', height='100%', type='application/x-shockwave-flash', data='https://cdn1.saucelabs.com/sauce_skin_deprecated/lib/flowplayer/flowplayer-3.2.17.swf', name='player_api', id='player_api'), id='player%s' % session, style='border:1px solid #e6e6e6; float:right; height:240px;' 'margin-left:5px; overflow:hidden; width:320px')
def _video_html(session): flash_vars = 'config={{\ "clip":{{\ "url":"{session}",\ "provider":"rtmp"}},\ "plugins":{{\ "controls":{{\ "url":"http://testingbot.com/assets/\ flowplayer.controls-3.2.14.swf",\ "mute":null,\ "volume":null}},\ "rtmp":{{\ "url":"http://testingbot.com/assets/\ flowplayer.rtmp-3.2.11.swf",\ "netConnectionUrl":"rtmp://s2tuay45tyrz3f.cloudfront.net/\ cfx/st"}}}},\ "playerId":"mediaplayer{session}",\ "playlist":[{{\ "url":"{session}",\ "provider":"rtmp"}}]}}'.format(session=session) return str( html.div( html.object( html.param(value="true", name="allowfullscreen"), html.param(value="always", name="allowscriptaccess"), html.param(value="high", name="quality"), html.param(value="#000000", name="bgcolor"), html.param(value="opaque", name="wmode"), html.param(value=flash_vars.replace(" ", ""), name="flashvars"), width="100%", height="100%", type="application/x-shockwave-flash", data="http://testingbot.com/assets/flowplayer-3.2.14.swf", name="mediaplayer_api", id="mediaplayer_api", ), id="mediaplayer{session}".format(session=session), style="border:1px solid #e6e6e6; float:right; height:240px;" "margin-left:5px; overflow:hidden; width:320px", ))
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_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 _video_html(self, session): flash_vars = 'config={{\ "clip":{{\ "url":"{0}",\ "provider":"rtmp"}},\ "plugins":{{\ "controls":{{\ "url":"http://testingbot.com/assets/\ flowplayer.controls-3.2.14.swf",\ "mute":null,\ "volume":null}},\ "rtmp":{{\ "url":"http://testingbot.com/assets/\ flowplayer.rtmp-3.2.11.swf",\ "netConnectionUrl":"rtmp://s2tuay45tyrz3f.cloudfront.net/\ cfx/st"}}}},\ "playerId":"mediaplayer{0}",\ "playlist":[{{\ "url":"{0}",\ "provider":"rtmp"}}]}}'.format(session) return str( html.div( html.object( html.param(value='true', name='allowfullscreen'), html.param(value='always', name='allowscriptaccess'), html.param(value='high', name='quality'), html.param(value='#000000', name='bgcolor'), html.param(value='opaque', name='wmode'), html.param(value=flash_vars.replace(' ', ''), name='flashvars'), width='100%', height='100%', type='application/x-shockwave-flash', data='http://testingbot.com/assets/flowplayer-3.2.14.swf', name='mediaplayer_api', id='mediaplayer_api'), id='mediaplayer{0}'.format(session), style='border:1px solid #e6e6e6; float:right; height:240px;' 'margin-left:5px; overflow:hidden; width:320px'))
def _generate_body(self, results_tree): body = html.body(onload="init()") generated_time = datetime.datetime.strptime( results_tree["suite_info"]["generated"].split(".")[0], "%Y-%I-%dT%X", ) summary_div = [ html.div( html.div(results_tree["name"], class_="project-title"), html.div( html.p('Report generated on {0} at {1} by'.format( generated_time.strftime('%d-%b-%Y'), generated_time.strftime('%H:%M:%S')), html.a(' pytest-html', href=__pypi_url__), ' v{0}'.format(__version__), class_="generated-time"), class_="generated-info", ), self._generate_environment( results_tree["suite_info"]["environment"], ), self._generate_summary_count( results_tree["suite_info"]["numtests"], results_tree["summary"], results_tree["suite_info"]["run_time"], ), class_="project-test-results-summary", ) ] self.config.hook.pytest_html_results_summary(summary=summary_div) results_div = [ html.div( html.h2("Results"), html.div( html.button("expand all", id="expand-all-button"), html.button("collapse all", id="collapse-all-button"), class_="show-hide-buttons", ), html.div(class_="results-info"), class_="results-details", ) ] body.extend([ summary_div, results_div, ]) return body
def _video_html(session): flash_vars = 'config={{\ "clip":{{\ "url":"{session}",\ "provider":"rtmp"}},\ "plugins":{{\ "controls":{{\ "url":"http://testingbot.com/assets/\ flowplayer.controls-3.2.14.swf",\ "mute":null,\ "volume":null}},\ "rtmp":{{\ "url":"http://testingbot.com/assets/\ flowplayer.rtmp-3.2.11.swf",\ "netConnectionUrl":"rtmp://s2tuay45tyrz3f.cloudfront.net/\ cfx/st"}}}},\ "playerId":"mediaplayer{session}",\ "playlist":[{{\ "url":"{session}",\ "provider":"rtmp"}}]}}'.format(session=session) return str(html.div(html.object( html.param(value='true', name='allowfullscreen'), html.param(value='always', name='allowscriptaccess'), html.param(value='high', name='quality'), html.param(value='#000000', name='bgcolor'), html.param(value='opaque', name='wmode'), html.param( value=flash_vars.replace(' ', ''), name='flashvars'), width='100%', height='100%', type='application/x-shockwave-flash', data='http://testingbot.com/assets/flowplayer-3.2.14.swf', name='mediaplayer_api', id='mediaplayer_api'), id='mediaplayer{session}'.format(session=session), style='border:1px solid #e6e6e6; float:right; height:240px;' 'margin-left:5px; overflow:hidden; width:320px'))
def video_html(self): flash_vars = 'config={\ "clip":{\ "url":"https%%3A//saucelabs.com/jobs/%(session_id)s/video.flv",\ "provider":"streamer",\ "autoPlay":false,\ "autoBuffering":true},\ "plugins":{\ "streamer":{\ "url":"https://saucelabs.com/flowplayer/flowplayer.pseudostreaming-3.2.5.swf"},\ "controls":{\ "mute":false,\ "volume":false,\ "backgroundColor":"rgba(0, 0, 0, 0.7)"}},\ "playerId":"player%(session_id)s",\ "playlist":[{\ "url":"https%%3A//saucelabs.com/jobs/%(session_id)s/video.flv",\ "provider":"streamer",\ "autoPlay":false,\ "autoBuffering":true}]}' % {'session_id': self.session_id} return html.div(html.object( html.param(value='true', name='allowfullscreen'), html.param(value='always', name='allowscriptaccess'), html.param(value='high', name='quality'), html.param(value='true', name='cachebusting'), html.param(value='#000000', name='bgcolor'), html.param( value=flash_vars.replace(' ', ''), name='flashvars'), width='100%', height='100%', type='application/x-shockwave-flash', data='https://saucelabs.com/flowplayer/flowplayer-3.2.5.swf?0.2930636672245027', name='player_api', id='player_api'), id='player%s' % self.session_id, class_='video')
def startDocument(self): super(IndexHandler, self).startDocument() self.head.append(html.script(type='text/javascript', src='apigen.js')) self._push(html.div(id='sidebar'))
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 append_extra_html(self, extra, extra_index, test_index): href = None if extra.get('format') == extras.FORMAT_IMAGE: content = extra.get('content') try: is_uri_or_path = (content.startswith(('file', 'http')) or isfile(content)) except ValueError: # On Windows, os.path.isfile throws this exception when # passed a b64 encoded image. is_uri_or_path = False if is_uri_or_path: if self.self_contained: warnings.warn('Self-contained HTML report ' 'includes link to external ' 'resource: {}'.format(content)) html_div = html.a(html.img(src=content), href=content) elif self.self_contained: src = 'data:{0};base64,{1}'.format( extra.get('mime_type'), content) html_div = html.img(src=src) else: if PY3: content = b64decode(content.encode('utf-8')) else: content = b64decode(content) href = src = self.create_asset( content, extra_index, test_index, extra.get('extension'), 'wb') html_div = html.a(html.img(src=src), href=href) self.additional_html.append(html.div(html_div, class_='image')) elif extra.get('format') == extras.FORMAT_HTML: self.additional_html.append(html.div( raw(extra.get('content')))) elif extra.get('format') == extras.FORMAT_JSON: content = json.dumps(extra.get('content')) if self.self_contained: href = data_uri(content, mime_type=extra.get('mime_type')) else: href = self.create_asset(content, extra_index, test_index, extra.get('extension')) elif extra.get('format') == extras.FORMAT_TEXT: content = extra.get('content') if isinstance(content, bytes): content = content.decode('utf-8') if self.self_contained: href = data_uri(content) else: href = self.create_asset(content, extra_index, test_index, extra.get('extension')) elif extra.get('format') == extras.FORMAT_URL: href = extra.get('content') if href is not None: self.links_html.append(html.a( extra.get('name'), class_=extra.get('format'), href=href, target='_blank')) self.links_html.append(' ')
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 test_inline(): h = html.div(html.span('foo'), html.span('bar')) assert (h.unicode(indent=2) == '<div><span>foo</span><span>bar</span></div>')
def make_result_html(self, data): cls_name = "" tc_name = unicode(data["test"]) tc_time = (data["time"] - self.start_times.pop(data["test"])) / 1000.0 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(): 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 debug.get("stdout", "").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) self.result_rows.append( html.tr( [ html.td(status_name, class_="col-result"), html.td(cls_name, class_="col-class"), html.td(tc_name, 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 _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 = "%s" % extra.get("content") if os.path.isfile(image): with open(image, "rb") as image_file: image_file = b64encode(image_file.read()) image = "data:image/png;base64,%s" % image_file else: image = "data:image/png;base64,%s" % image 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 endDocument(self): maindiv = html.div(id="main") maindiv.append(html.div(id="breadcrumb")) maindiv.append(html.iframe(name='content', id='content', src='module_py.html')) self.body.append(maindiv)