Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Environment table #286

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ via the :code:`pytest_configure` hook:
The generated table will be sorted alphabetically unless the metadata is a
:code:`collections.OrderedDict`.

You can edit the environment table header and row by using the :code:`pytest_html_environment_table_header` and `pytest_html_environment_table_row` hooks:

.. code-block:: python

import pytest

DESCRIPTION_DICT = {"Packages": "Version of pytest packages", "Python": "Version of Python"}

def pytest_html_environment_table_header(cells):
cells.insert(2, html.th('Description'))

def pytest_html_environment_table_row(cells):
cells.insert(2, html.td(description_dict.get(cells[0], '')))


Additional summary information
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
8 changes: 8 additions & 0 deletions pytest_html/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ def pytest_html_report_title(report):
""" Called before adding the title to the report """


def pytest_html_environment_table_header(cells):
""" Called after building environment table header. """


def pytest_html_environment_table_row(cells):
""" Called after building environment table row. """


def pytest_html_results_summary(prefix, summary, postfix):
""" Called before adding the summary section to the report """

Expand Down
74 changes: 46 additions & 28 deletions pytest_html/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,51 @@ def _append_video(self, extra, extra_index, test_index):
)
self.additional_html.append(html.div(html_div, class_="video"))

class EnvironmentSection:
def __init__(self, config):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would split this big init up into smaller functions.

Think builder pattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really sure to understand what to do here, I agree that everything in the init is not good but the function I can think of (generate_header, generate_row, ...) are very small... Do you want something like that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm having trouble articulating the vision I have in my head. Give me the weekend to see if I can throw something together that you can refine. :)

self.metadata = getattr(config, "_metadata", [])
self.config = config
self.environment = []
self.environment_table = []
self.rows = []

if self.metadata:
self._generate_environment_header()

keys = [k for k in self.metadata.keys()]
if not isinstance(self.metadata, OrderedDict):
keys.sort()

for key in keys:
self._generate_environment_row(key)

self._generate_environment_section()

def _generate_environment_header(self):
header_cells = [html.th("Key"), html.th("Value")]
self.config.hook.pytest_html_environment_table_header(cells=header_cells)
self.rows.append(header_cells)

def _generate_environment_row(self, key):
value = self.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))
row_cells = html.tr(html.td(key), html.td(raw_value_string))
self.config.hook.pytest_html_environment_table_row(cells=row_cells)
self.rows.append(row_cells)

def _generate_environment_section(self):
if self.rows:
self.environment_table.append(html.table(self.rows, id="environment"))
self.environment = [html.h2("Environment")]
self.environment.append(self.environment_table)

def _appendrow(self, outcome, report):
result = self.TestResult(outcome, report, self.logfile, self.config)
if result.row_table is not None:
Expand Down Expand Up @@ -551,7 +596,7 @@ def generate_summary_item(self):
onLoad="init()",
)

body.extend(self._generate_environment(session.config))
body.extend(self.EnvironmentSection(session.config).environment)

summary_prefix, summary_postfix = [], []
session.config.hook.pytest_html_results_summary(
Expand All @@ -569,33 +614,6 @@ def generate_summary_item(self):
unicode_doc = unicode_doc.encode("utf-8", errors="xmlcharrefreplace")
return unicode_doc.decode("utf-8")

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):
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(key), html.td(raw_value_string)))

environment.append(html.table(rows, id="environment"))
return environment

def _save_report(self, report_content):
dir_name = os.path.dirname(self.logfile)
assets_dir = os.path.join(dir_name, "assets")
Expand Down