def __init__( self, latex=False, inline=False, dark_bg=True, font_size="normal", linkify=False, escaped=True, markup_lines=False, output_encoding="utf-8", scheme="ansi2html", title="", ): self.latex = latex self.inline = inline self.dark_bg = dark_bg self.font_size = font_size self.linkify = linkify self.escaped = escaped self.markup_lines = markup_lines self.output_encoding = output_encoding self.scheme = scheme self.title = title self._attrs = None if inline: self.styles = dict([(item.klass.strip("."), item) for item in get_styles(self.dark_bg, self.scheme)]) self.ansi_codes_prog = re.compile("\?\\[" "([\\d;]*)" "([a-zA-z])")
def __init__(self, latex=False, inline=False, dark_bg=True, font_size='normal', linkify=False, escaped=True, markup_lines=False, output_encoding='utf-8', scheme='ansi2html', title='' ): self.latex = latex self.inline = inline self.dark_bg = dark_bg self.font_size = font_size self.linkify = linkify self.escaped = escaped self.markup_lines = markup_lines self.output_encoding = output_encoding self.scheme = scheme self.title = title self._attrs = None if inline: self.styles = dict([(item.klass.strip('.'), item) for item in get_styles(self.dark_bg, self.scheme)]) self.ansi_codes_prog = re.compile('\033\\[' '([\\d;]*)' '([a-zA-z])')
def convert(self, ansi, full=True): attrs = self.prepare(ansi) if not full: return attrs["body"] else: return _template % { 'style' : "\n".join(map(str, get_styles(self.dark_bg))), 'font_size' : self.font_size, 'content' : attrs["body"], 'output_encoding' : self.output_encoding, }
def media(self): """Add inline styling for rendered.""" return super(LogAdminMixin, self).media + forms.Media(css={'all': ( emb.CSS("\n".join(str(style) for style in get_styles(dark_bg=False))), emb.CSS(""" .grp-readonly .ansi2html-content { white-space: pre-wrap !important; word-wrap: break-word; font-family: monospace; } .ansi2html-container { max-height: 500px; overflow: auto; } """))})
def convert(self, ansi, full=True, ensure_trailing_newline=False): attrs = self.prepare(ansi, ensure_trailing_newline=ensure_trailing_newline) if not full: return attrs["body"] else: if self.latex: _template = _latex_template else: _template = _html_template return _template % { 'style' : "\n".join(map(str, get_styles(self.dark_bg, self.scheme))), 'title' : self.title, 'font_size' : self.font_size, 'content' : attrs["body"], 'output_encoding' : self.output_encoding, }
def convert(self, ansi, full=True, ensure_trailing_newline=False): attrs = self.prepare(ansi, ensure_trailing_newline=ensure_trailing_newline) if not full: return attrs["body"] else: if self.latex: _template = _latex_template else: _template = _html_template all_styles = get_styles(self.dark_bg, self.line_wrap, self.scheme) backgrounds = all_styles[:6] used_styles = filter(lambda e: e.klass.lstrip(".") in attrs["styles"], all_styles) return _template % { 'style' : "\n".join(list(map(str, backgrounds + list(used_styles)))), 'title' : self.title, 'font_size' : self.font_size, 'content' : attrs["body"], 'output_encoding' : self.output_encoding, }
def get_style(self): return '<style>' + \ "\n".join(map(str, get_styles(self.dark_bg, self.scheme))) + \ '</style>'
import json from jinja2 import Template from ansi2html import Ansi2HTMLConverter from ansi2html.style import get_styles conv = Ansi2HTMLConverter() def shell_to_html(shell): return conv.convert(shell, False) if __name__ == '__main__': result = Template(open("template.html", "r").read()).render(data=json.load(open("./logs.json")), convert=shell_to_html, shell_css="\n".join(map(str, get_styles(conv.dark_bg, conv.scheme)))) open("index.html", "w").write(result.encode("Utf-8"))
def produce_headers(self): return '<style type="text/css">\n%(style)s\n</style>\n' % { 'style' : "\n".join(map(str, get_styles(self.dark_bg, self.scheme))) }
def _generate_report(self, session): 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() self.style_css = pkg_resources.resource_string( __name__, os.path.join('resources', 'style.css')) if PY3: self.style_css = self.style_css.decode('utf-8') if ANSI: ansi_css = [ '\n/******************************', ' * ANSI2HTML STYLES', ' ******************************/\n'] ansi_css.extend([str(r) for r in style.get_styles()]) self.style_css += '\n'.join(ansi_css) # <DF> Add user-provided CSS for path in self.config.getoption('css') or []: self.style_css += '\n/******************************' self.style_css += '\n * CUSTOM CSS' self.style_css += '\n * {}'.format(path) self.style_css += '\n ******************************/\n\n' with open(path, 'r') as f: self.style_css += f.read() css_href = '{0}/{1}'.format('assets', 'style.css') html_css = html.link(href=css_href, rel='stylesheet', type='text/css') if self.self_contained: html_css = html.style(raw(self.style_css)) head = html.head( html.meta(charset='utf-8'), html.title('Test Report'), html_css) class Outcome: def __init__(self, outcome, total=0, label=None, test_result=None, class_html=None): self.outcome = outcome self.label = label or outcome self.class_html = class_html or outcome self.total = total self.test_result = test_result or outcome self.generate_checkbox() self.generate_summary_item() def generate_checkbox(self): checkbox_kwargs = {'data-test-result': self.test_result.lower()} if self.total == 0: checkbox_kwargs['disabled'] = 'true' self.checkbox = html.input(type='checkbox', checked='true', onChange='filter_table(this)', name='filter_checkbox', class_='filter', hidden='true', **checkbox_kwargs) def generate_summary_item(self): self.summary_item = html.span('{0} {1}'. format(self.total, self.label), class_=self.class_html) outcomes = [Outcome('passed', self.passed), Outcome('skipped', self.skipped), Outcome('failed', self.failed), Outcome('error', self.errors, label='errors'), Outcome('xfailed', self.xfailed, label='expected failures'), Outcome('xpassed', self.xpassed, label='unexpected passes')] if self.rerun is not None: outcomes.append(Outcome('rerun', self.rerun)) summary = [html.p( '{0} tests ran in {1:.2f} seconds. '.format( numtests, suite_time_delta)), html.p('(Un)check the boxes to filter the results.', class_='filter', hidden='true')] for i, outcome in enumerate(outcomes, start=1): summary.append(outcome.checkbox) summary.append(outcome.summary_item) if i < len(outcomes): summary.append(', ') cells = [ html.th('Result', class_='sortable result initial-sort', col='result'), html.th('Test', class_='sortable', col='name'), html.th('Duration', class_='sortable numeric', col='duration'), html.th('Links')] session.config.hook.pytest_html_results_table_header(cells=cells) results = [html.h2('Results'), html.table([html.thead( html.tr(cells), html.tr([ html.th('No results found. Try to check the filters', colspan=len(cells))], id='not-found-message', hidden='true'), id='results-table-head'), self.test_logs], 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.h1(os.path.basename(session.config.option.htmlpath)), html.p('Report generated on {0} at {1} by'.format( generated.strftime('%d-%b-%Y'), generated.strftime('%H:%M:%S')), html.a(' pytest-html', href=__pypi_url__), ' v{0}'.format(__version__)), onLoad='init()') body.extend(self._generate_environment(session.config)) summary_prefix, summary_postfix = [], [] session.config.hook.pytest_html_results_summary( prefix=summary_prefix, summary=summary, postfix=summary_postfix) body.extend([html.h2('Summary')] + summary_prefix + summary + summary_postfix) body.extend(results) doc = html.html(head, body) unicode_doc = u'<!DOCTYPE html>\n{0}'.format(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') return unicode_doc
def _generate_report(self, session): 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() self.style_css = pkg_resources.resource_string( __name__, os.path.join("resources", "style.css")).decode("utf-8") if ANSI: ansi_css = [ "\n/******************************", " * ANSI2HTML STYLES", " ******************************/\n", ] ansi_css.extend([str(r) for r in style.get_styles()]) self.style_css += "\n".join(ansi_css) # <DF> Add user-provided CSS for path in self.config.getoption("css"): self.style_css += "\n/******************************" self.style_css += "\n * CUSTOM CSS" self.style_css += f"\n * {path}" self.style_css += "\n ******************************/\n\n" with open(path, "r") as f: self.style_css += f.read() css_href = "assets/style.css" html_css = html.link(href=css_href, rel="stylesheet", type="text/css") if self.self_contained: html_css = html.style(raw(self.style_css)) head = html.head(html.meta(charset="utf-8"), html.title("Test Report"), html_css) class Outcome: def __init__(self, outcome, total=0, label=None, test_result=None, class_html=None): self.outcome = outcome self.label = label or outcome self.class_html = class_html or outcome self.total = total self.test_result = test_result or outcome self.generate_checkbox() self.generate_summary_item() def generate_checkbox(self): checkbox_kwargs = { "data-test-result": self.test_result.lower() } if self.total == 0: checkbox_kwargs["disabled"] = "true" self.checkbox = html.input( type="checkbox", checked="true", onChange="filter_table(this)", name="filter_checkbox", class_="filter", hidden="true", **checkbox_kwargs, ) def generate_summary_item(self): self.summary_item = html.span(f"{self.total} {self.label}", class_=self.class_html) outcomes = [ Outcome("passed", self.passed), Outcome("skipped", self.skipped), Outcome("failed", self.failed), Outcome("error", self.errors, label="errors"), Outcome("xfailed", self.xfailed, label="expected failures"), Outcome("xpassed", self.xpassed, label="unexpected passes"), ] if self.rerun is not None: outcomes.append(Outcome("rerun", self.rerun)) summary = [ html.p( f"{numtests} tests ran in {suite_time_delta:.2f} seconds. "), html.p( "(Un)check the boxes to filter the results.", class_="filter", hidden="true", ), ] for i, outcome in enumerate(outcomes, start=1): summary.append(outcome.checkbox) summary.append(outcome.summary_item) if i < len(outcomes): summary.append(", ") cells = [ html.th("Result", class_="sortable result initial-sort", col="result"), html.th("Test", class_="sortable", col="name"), html.th("Duration", class_="sortable numeric", col="duration"), html.th("Links"), ] session.config.hook.pytest_html_results_table_header(cells=cells) results = [ html.h2("Results"), html.table( [ html.thead( html.tr(cells), html.tr( [ html.th( "No results found. Try to check the filters", colspan=len(cells), ) ], id="not-found-message", hidden="true", ), id="results-table-head", ), self.test_logs, ], id="results-table", ), ] main_js = pkg_resources.resource_string( __name__, os.path.join("resources", "main.js")).decode("utf-8") body = html.body( html.script(raw(main_js)), html.h1(os.path.basename(self.logfile)), html.p( "Report generated on {} at {} by ".format( generated.strftime("%d-%b-%Y"), generated.strftime("%H:%M:%S")), html.a("pytest-html", href=__pypi_url__), f" v{__version__}", ), onLoad="init()", ) body.extend(self._generate_environment(session.config)) summary_prefix, summary_postfix = [], [] session.config.hook.pytest_html_results_summary( prefix=summary_prefix, summary=summary, postfix=summary_postfix) body.extend([html.h2("Summary")] + summary_prefix + summary + summary_postfix) body.extend(results) doc = html.html(head, body) unicode_doc = "<!DOCTYPE html>\n{}".format(doc.unicode(indent=2)) # Fix encoding issues, e.g. with surrogates unicode_doc = unicode_doc.encode("utf-8", errors="xmlcharrefreplace") return unicode_doc.decode("utf-8")
def _generate_report(self, session): 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() self.style_css = pkg_resources.resource_string( __name__, os.path.join('resources', 'style.css')) if PY3: self.style_css = self.style_css.decode('utf-8') if ANSI: ansi_css = [ '\n/******************************', ' * ANSI2HTML STYLES', ' ******************************/\n' ] ansi_css.extend([str(r) for r in style.get_styles()]) self.style_css += '\n'.join(ansi_css) css_href = '{0}/{1}'.format('assets', 'style.css') html_css = html.link(href=css_href, rel='stylesheet', type='text/css') if self.self_contained: html_css = html.style(raw(self.style_css)) head = html.head(html.meta(charset='utf-8'), html.title('Test Report'), html_css) class Outcome: def __init__(self, outcome, total=0, label=None, test_result=None, class_html=None): self.outcome = outcome self.label = label or outcome self.class_html = class_html or outcome self.total = total self.test_result = test_result or outcome self.generate_checkbox() self.generate_summary_item() def generate_checkbox(self): checkbox_kwargs = { 'data-test-result': self.test_result.lower() } if self.total == 0: checkbox_kwargs['disabled'] = 'true' self.checkbox = html.input(type='checkbox', checked='true', onChange='filter_table(this)', name='filter_checkbox', class_='filter', hidden='true', **checkbox_kwargs) def generate_summary_item(self): self.summary_item = html.span('{0} {1}'.format( self.total, self.label), class_=self.class_html) outcomes = [ Outcome('passed', self.passed), Outcome('skipped', self.skipped), Outcome('failed', self.failed), Outcome('error', self.errors, label='errors'), Outcome('xfailed', self.xfailed, label='expected failures'), Outcome('xpassed', self.xpassed, label='unexpected passes') ] if self.rerun is not None: outcomes.append(Outcome('rerun', self.rerun)) summary = [ html.h2('Summary'), html.p('{0} tests ran in {1:.2f} seconds. '.format( numtests, suite_time_delta)), html.p('(Un)check the boxes to filter the results.', class_='filter', hidden='true') ] for i, outcome in enumerate(outcomes, start=1): summary.append(outcome.checkbox) summary.append(outcome.summary_item) if i < len(outcomes): summary.append(', ') results = [ html.h2('Results'), html.table([ html.thead( html.tr([ html.th('Result', class_='sortable result initial-sort', col='result'), html.th('Test', class_='sortable', col='name'), html.th('Duration', class_='sortable numeric', col='duration'), html.th('Links') ]), html.tr([ html.th('No results found. Try to check the filters', colspan='5') ], id='not-found-message', hidden='true'), id='results-table-head'), self.test_logs ], 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} by'.format( generated.strftime('%d-%b-%Y'), generated.strftime('%H:%M:%S')), html.a(' pytest-html', href=__pypi_url__), ' v{0}'.format(__version__)), onLoad='init()') 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) unicode_doc = u'<!DOCTYPE html>\n{0}'.format(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') return unicode_doc
def produce_headers(self): return '<style type="text/css">\n%(style)s\n</style>\n' % { 'style': "\n".join(map(str, get_styles(self.dark_bg, self.scheme))) }
def _generate_report(self, session): 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() self.style_css = pkg_resources.resource_string( __name__, os.path.join('resources', 'style.css')) if PY3: self.style_css = self.style_css.decode('utf-8') if ANSI: ansi_css = [ '\n/******************************', ' * ANSI2HTML STYLES', ' ******************************/\n' ] ansi_css.extend([str(r) for r in style.get_styles()]) self.style_css += '\n'.join(ansi_css) # <DF> Add user-provided CSS for path in self.config.getoption('css'): self.style_css += '\n/******************************' self.style_css += '\n * CUSTOM CSS' self.style_css += '\n * {}'.format(path) self.style_css += '\n ******************************/\n\n' with open(path, 'r') as f: self.style_css += f.read() css_href = '{0}/{1}'.format('assets', 'style.css') html_css = html.link(href=css_href, rel='stylesheet', type='text/css') if self.self_contained: html_css = html.style(raw(self.style_css)) # head = html.head( # html.meta(charset='utf-8'), # html.title('Test Report'), # html_css) head = html.head( # modify by linux超 html.meta(charset='utf-8'), html.title('测试报告'), html_css) class Outcome: def __init__(self, outcome, total=0, label=None, test_result=None, class_html=None): self.outcome = outcome self.label = label or outcome self.class_html = class_html or outcome self.total = total self.test_result = test_result or outcome self.generate_checkbox() self.generate_summary_item() def generate_checkbox(self): checkbox_kwargs = { 'data-test-result': self.test_result.lower() } if self.total == 0: checkbox_kwargs['disabled'] = 'true' self.checkbox = html.input(type='checkbox', checked='true', onChange='filter_table(this)', name='filter_checkbox', class_='filter', hidden='true', **checkbox_kwargs) def generate_summary_item(self): self.summary_item = html.span('{0} {1}'.format( self.total, self.label), class_=self.class_html) # outcomes = [Outcome('passed', self.passed), # Outcome('skipped', self.skipped), # Outcome('failed', self.failed), # Outcome('error', self.errors, label='errors'), # Outcome('xfailed', self.xfailed, # label='expected failures'), # Outcome('xpassed', self.xpassed, # label='unexpected passes')] outcomes = [ Outcome('passed', self.passed, label="通过"), Outcome('skipped', self.skipped, label="跳过"), Outcome('failed', self.failed, label="失败"), Outcome('error', self.errors, label='错误'), Outcome('xfailed', self.xfailed, label='预期失败'), Outcome('xpassed', self.xpassed, label='预期通过') ] # if self.rerun is not None: # outcomes.append(Outcome('rerun', self.rerun)) if self.rerun is not None: outcomes.append(Outcome('重跑', self.rerun)) # summary = [html.p( # '{0} tests ran in {1:.2f} seconds. '.format( # numtests, suite_time_delta)), # html.p('sfsf', # class_='filter', # hidden='true')] summary = [ html.p( # modify by linux超 '执行了{0}个测试用例, 历时:{1:.2f}秒 . '.format(numtests, suite_time_delta)), html.p('(取消)勾选复选框, 以便筛选测试结果', class_='filter', hidden='true') ] for i, outcome in enumerate(outcomes, start=1): summary.append(outcome.checkbox) summary.append(outcome.summary_item) if i < len(outcomes): summary.append(', ') # cells = [ # html.th('Result', # class_='sortable result initial-sort', # col='result'), # html.th('Test', class_='sortable', col='name'), # html.th('Duration', class_='sortable numeric', col='duration'), # html.th('Links')]# modify by linux超 cells = [ html.th('通过/失败', class_='sortable result initial-sort', col='result'), html.th('用例', class_='sortable', col='name'), html.th('耗时', class_='sortable numeric', col='duration'), html.th('链接') ] session.config.hook.pytest_html_results_table_header(cells=cells) # results = [html.h2('Results'), html.table([html.thead( # html.tr(cells), # html.tr([ # html.th('No results found. Try to check the filters', # colspan=len(cells))], # id='not-found-message', hidden='true'), # id='results-table-head'), # self.test_logs], id='results-table')] results = [ html.h2('测试结果'), html.table( [ html.thead( # modify by linux超 html.tr(cells), html.tr([ html.th('无测试结果, 试着选择其他测试结果条件', colspan=len(cells)) ], id='not-found-message', hidden='true'), id='results-table-head'), self.test_logs ], 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.h1(os.path.basename(session.config.option.htmlpath)), # html.p('Report generated on {0} at {1} by '.format( html.p( '生成报告时间{0} {1} Pytest-Html版本:'.format( # modify by linux超 generated.strftime('%d-%b-%Y'), generated.strftime('%H:%M:%S')), html.a('pytest-html', href=__pypi_url__), ' v{0}'.format(__version__)), onLoad='init()') body.extend(self._generate_environment(session.config)) summary_prefix, summary_postfix = [], [] session.config.hook.pytest_html_results_summary( prefix=summary_prefix, summary=summary, postfix=summary_postfix) # body.extend([html.h2('Summary')] + summary_prefix # + summary + summary_postfix) body.extend([html.h2('用例统计')] + summary_prefix # modify by linux超 + summary + summary_postfix) body.extend(results) doc = html.html(head, body) unicode_doc = u'<!DOCTYPE html>\n{0}'.format(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') return unicode_doc
HEADER = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' WARNING = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' BOLD = '\033[1m' UNDERLINE = '\033[4m' highlight_keywords = r"(fail|warning|no such|error|closed connection|unknown|traceback|unable)" ############################################################################### conv = Ansi2HTMLConverter() shell_css = "\n".join(map(str, get_styles(conv.dark_bg, conv.scheme))) def shell_to_html(shell): return conv.convert(shell, False) ############################################################################### if __name__ == '__main__': # Fetch the list of all reports, sorted in reverse-chronological order report_paths.sort(reverse=True) reports = []