From f6f623d0d9884950390b8aee032b619ceeb11d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jim=20Br=C3=A4nnlund?= Date: Sat, 22 Jul 2023 15:06:29 +0200 Subject: [PATCH] Chore: Simplify results table hooks (#688) --- pyproject.toml | 2 +- src/pytest_html/basereport.py | 72 ++++++++++++++------- src/pytest_html/report_data.py | 14 ++++- src/pytest_html/resources/index.jinja2 | 11 ---- src/pytest_html/resources/style.css | 4 +- src/pytest_html/scripts/datamanager.js | 3 + src/pytest_html/scripts/dom.js | 61 ++++-------------- src/pytest_html/scripts/main.js | 25 ++------ src/pytest_html/scripts/utils.js | 41 ------------ src/pytest_html/table.py | 86 -------------------------- testing/legacy_test_pytest_html.py | 1 - testing/test_integration.py | 2 +- testing/unittest.js | 32 ---------- 13 files changed, 86 insertions(+), 268 deletions(-) delete mode 100644 src/pytest_html/scripts/utils.js delete mode 100644 src/pytest_html/table.py diff --git a/pyproject.toml b/pyproject.toml index e4bf9116..9bd04733 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ classifiers = [ ] dependencies = [ "pytest>=7.0.0", - "pytest-metadata>=2.0.2", + "pytest-metadata>=3.0.0", "Jinja2>=3.0.0", ] dynamic = [ diff --git a/src/pytest_html/basereport.py b/src/pytest_html/basereport.py index 52180428..8d0e8de7 100644 --- a/src/pytest_html/basereport.py +++ b/src/pytest_html/basereport.py @@ -3,17 +3,17 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. import datetime import json +import math import os import re import warnings from pathlib import Path import pytest +from pytest_metadata.plugin import metadata_key from pytest_html import __version__ from pytest_html import extras -from pytest_html.table import Header -from pytest_html.table import Row from pytest_html.util import cleanup_unserializable @@ -60,8 +60,8 @@ def _generate_report(self, self_contained=False): self._write_report(rendered_report) - def _generate_environment(self): - metadata = self._config._metadata + def _generate_environment(self, metadata_key): + metadata = self._config.stash[metadata_key] for key in metadata.keys(): value = metadata[key] if self._is_redactable_environment_variable(key): @@ -145,16 +145,12 @@ def _write_report(self, rendered_report): @pytest.hookimpl(trylast=True) def pytest_sessionstart(self, session): - config = session.config - if hasattr(config, "_metadata") and config._metadata: - self._report.set_data("environment", self._generate_environment()) + self._report.set_data("environment", self._generate_environment(metadata_key)) session.config.hook.pytest_html_report_title(report=self._report) - header_cells = Header() - session.config.hook.pytest_html_results_table_header(cells=header_cells) - self._report.set_data("resultsTableHeader", header_cells.html) - self._report.set_data("headerPops", header_cells.get_pops()) + headers = self._report.data["resultsTableHeader"] + session.config.hook.pytest_html_results_table_header(cells=headers) self._report.set_data("runningState", "Started") self._generate_report() @@ -173,7 +169,8 @@ def pytest_sessionfinish(self, session): @pytest.hookimpl(trylast=True) def pytest_terminal_summary(self, terminalreporter): terminalreporter.write_sep( - "-", f"Generated html report: file://{self._report_path.resolve()}" + "-", + f"Generated html report: file://{self._report_path.resolve().as_posix()}", ) @pytest.hookimpl(trylast=True) @@ -189,34 +186,60 @@ def pytest_runtest_logreport(self, report): ) data = { - "duration": report.duration, + "result": _process_outcome(report), + "duration": _format_duration(report.duration), } + total_duration = self._report.data["totalDuration"] + total_duration["total"] += report.duration + total_duration["formatted"] = _format_duration(total_duration["total"]) + test_id = report.nodeid if report.when != "call": test_id += f"::{report.when}" data["testId"] = test_id - row_cells = Row() - self._config.hook.pytest_html_results_table_row(report=report, cells=row_cells) - if row_cells.html is None: + data["extras"] = self._process_extras(report, test_id) + links = [ + extra + for extra in data["extras"] + if extra["format_type"] in ["json", "text", "url"] + ] + cells = [ + f'{data["result"]}', + f'{data["testId"]}', + f'{data["duration"]}', + f'{_process_links(links)}', + ] + + self._config.hook.pytest_html_results_table_row(report=report, cells=cells) + if not cells: return - data["resultsTableRow"] = row_cells.html - for sortable, value in row_cells.sortables.items(): - data[sortable] = value + + data["resultsTableRow"] = cells processed_logs = _process_logs(report) self._config.hook.pytest_html_results_table_html( report=report, data=processed_logs ) - data["result"] = _process_outcome(report) - data["extras"] = self._process_extras(report, test_id) - if self._report.add_test(data, report, processed_logs): self._generate_report() +def _format_duration(duration): + if duration < 1: + return "{} ms".format(round(duration * 1000)) + + hours = math.floor(duration / 3600) + remaining_seconds = duration % 3600 + minutes = math.floor(remaining_seconds / 60) + remaining_seconds = remaining_seconds % 60 + seconds = round(remaining_seconds) + + return f"{hours:02d}:{minutes:02d}:{seconds:02d}" + + def _is_error(report): return report.when in ["setup", "teardown"] and report.outcome == "failed" @@ -249,3 +272,8 @@ def _process_outcome(report): return "XFailed" return report.outcome.capitalize() + + +def _process_links(links): + a_tag = '{name}' + return "".join([a_tag.format_map(link) for link in links]) diff --git a/src/pytest_html/report_data.py b/src/pytest_html/report_data.py index aee5e938..d797c7ca 100644 --- a/src/pytest_html/report_data.py +++ b/src/pytest_html/report_data.py @@ -10,14 +10,26 @@ class ReportData: def __init__(self, config): self._config = config + + default_headers = [ + 'Result', + 'Test', + 'Duration', + "Links", + ] + self._data = { "title": "", "collectedItems": 0, + "totalDuration": { + "total": 0, + "formatted": "", + }, "runningState": "not_started", "environment": {}, "tests": defaultdict(list), - "resultsTableHeader": {}, "additionalSummary": defaultdict(list), + "resultsTableHeader": default_headers, } collapsed = config.getini("render_collapsed") diff --git a/src/pytest_html/resources/index.jinja2 b/src/pytest_html/resources/index.jinja2 index 8f56d97f..878d04e1 100644 --- a/src/pytest_html/resources/index.jinja2 +++ b/src/pytest_html/resources/index.jinja2 @@ -26,16 +26,9 @@ -