diff --git a/src/pytest_html/basereport.py b/src/pytest_html/basereport.py index b160e910..33038de2 100644 --- a/src/pytest_html/basereport.py +++ b/src/pytest_html/basereport.py @@ -7,6 +7,7 @@ import os import re import warnings +from collections import defaultdict from pathlib import Path import pytest @@ -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 @@ -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": @@ -229,7 +266,7 @@ def pytest_runtest_logreport(self, report): cells = [ f'