Skip to content

Commit

Permalink
fix: Broken duration (pytest-dev#753)
Browse files Browse the repository at this point in the history
  • Loading branch information
BeyondEvil authored Oct 31, 2023
1 parent 8523105 commit 263c1c6
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 15 deletions.
54 changes: 43 additions & 11 deletions src/pytest_html/basereport.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
import re
import warnings
from collections import defaultdict
from pathlib import Path

import pytest
Expand All @@ -29,6 +30,7 @@ def __init__(self, report_path, config, report_data, template, css):
config.getini("max_asset_filename_length")
)

self._reports = defaultdict(dict)
self._report = report_data
self._report.title = self._report_path.name

Expand Down Expand Up @@ -204,15 +206,50 @@ def pytest_runtest_logreport(self, report):
DeprecationWarning,
)

# "reruns" makes this code a mess.
# We store each combination of when and outcome
# exactly once, unless that outcome is a "rerun"
# then we store all of them.
key = (report.when, report.outcome)
if report.outcome == "rerun":
if key not in self._reports[report.nodeid]:
self._reports[report.nodeid][key] = list()
self._reports[report.nodeid][key].append(report)
else:
self._reports[report.nodeid][key] = [report]

self._report.total_duration += report.duration

finished = report.when == "teardown" and report.outcome != "rerun"
if not finished:
return

# Calculate total duration for a single test.
# This is needed to add the "teardown" duration
# to tests total duration.
test_duration = 0
for key, reports in self._reports[report.nodeid].items():
_, outcome = key
if outcome != "rerun":
test_duration += reports[0].duration

for key, reports in self._reports[report.nodeid].items():
when, _ = key
for each in reports:
dur = test_duration if when == "call" else each.duration
self._process_report(each, dur)

self._generate_report()

def _process_report(self, report, duration):
outcome = _process_outcome(report)
try:
# hook returns as list for some reason
duration = self._config.hook.pytest_html_duration_format(
duration=report.duration
formatted_duration = self._config.hook.pytest_html_duration_format(
duration=duration
)[0]
except IndexError:
duration = _format_duration(report.duration)
self._report.total_duration += report.duration
formatted_duration = _format_duration(duration)

test_id = report.nodeid
if report.when != "call":
Expand All @@ -229,7 +266,7 @@ def pytest_runtest_logreport(self, report):
cells = [
f'<td class="col-result">{outcome}</td>',
f'<td class="col-testId">{test_id}</td>',
f'<td class="col-duration">{duration}</td>',
f'<td class="col-duration">{formatted_duration}</td>',
f'<td class="col-links">{_process_links(links)}</td>',
]
self._config.hook.pytest_html_results_table_row(report=report, cells=cells)
Expand All @@ -240,17 +277,12 @@ def pytest_runtest_logreport(self, report):
self._hydrate_data(data, cells)
data["resultsTableRow"] = cells

# don't count passed setups and teardowns
if not (report.when in ["setup", "teardown"] and report.outcome == "passed"):
self._report.outcomes = outcome

processed_logs = _process_logs(report)
self._config.hook.pytest_html_results_table_html(
report=report, data=processed_logs
)

if self._report.add_test(data, report, processed_logs):
self._generate_report()
self._report.add_test(data, report, outcome, processed_logs)


def _format_duration(duration):
Expand Down
6 changes: 2 additions & 4 deletions src/pytest_html/report_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def total_duration(self, duration):
def set_data(self, key, value):
self._data[key] = value

def add_test(self, test_data, report, logs):
def add_test(self, test_data, report, outcome, logs):
# regardless of pass or fail we must add teardown logging to "call"
if report.when == "teardown":
self.append_teardown_log(report)
Expand All @@ -137,10 +137,8 @@ def add_test(self, test_data, report, logs):
report.when in ["setup", "teardown"] and report.outcome != "passed"
):
test_data["log"] = _handle_ansi("\n".join(logs))
self.outcomes = outcome
self._data["tests"][report.nodeid].append(test_data)
return True

return False

def append_teardown_log(self, report):
log = []
Expand Down

0 comments on commit 263c1c6

Please sign in to comment.