Skip to content

Commit

Permalink
Feat: Add duration format hook (pytest-dev#724)
Browse files Browse the repository at this point in the history
  • Loading branch information
BeyondEvil authored Sep 1, 2023
1 parent 372acd8 commit b7c50c1
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 2 deletions.
22 changes: 22 additions & 0 deletions docs/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,28 @@ Note that the values are case *sensitive*.
If tests are run in parallel (with `pytest-xdist`_ for example), then the order may not be
in the correct order.

Formatting the Duration Column
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The formatting of the timestamp used in the :code:`Durations` column can be modified by using the
:code:`pytest_html_duration_format` hook. The default timestamp will be `nnn ms` for durations
less than one second and `hh:mm:ss` for durations equal to or greater than one second.

Below is an example of a :code:`conftest.py` file setting :code:`pytest_html_duration_format`:

.. code-block:: python
import datetime
def pytest_html_duration_format(duration):
duration_timedelta = datetime.timedelta(seconds=duration)
time = datetime.datetime(1, 1, 1) + duration_timedelta
return time.strftime("%H:%M:%S")
**NOTE**: The behavior of sorting the duration column is not guaranteed when providing a custom format.

**NOTE**: The formatting of the total duration is not affected by this hook.

.. _@pytest.hookimpl(tryfirst=True): https://docs.pytest.org/en/stable/writing_plugins.html#hook-function-ordering-call-example
.. _ansi2html: https://pypi.python.org/pypi/ansi2html/
Expand Down
11 changes: 9 additions & 2 deletions src/pytest_html/basereport.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,19 @@ def pytest_collection_finish(self, session):
def pytest_runtest_logreport(self, report):
if hasattr(report, "duration_formatter"):
warnings.warn(
"'duration_formatter' has been removed and no longer has any effect!",
"'duration_formatter' has been removed and no longer has any effect!"
"Please use the 'pytest_html_duration_format' hook instead.",
DeprecationWarning,
)

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

test_id = report.nodeid
Expand Down
4 changes: 4 additions & 0 deletions src/pytest_html/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ def pytest_html_results_table_row(report, cells):

def pytest_html_results_table_html(report, data):
"""Called after building results table additional HTML."""


def pytest_html_duration_format(duration):
"""Called before using the default duration formatting."""
15 changes: 15 additions & 0 deletions testing/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,21 @@ def test_sleep():
assert_that(duration).matches(expectation)
assert_that(total_duration).matches(r"\d{2}:\d{2}:\d{2}")

def test_duration_format_hook(self, pytester):
pytester.makeconftest(
"""
def pytest_html_duration_format(duration):
return str(round(duration * 1000)) + " seconds"
"""
)

pytester.makepyfile("def test_pass(): pass")
page = run(pytester)
assert_results(page, passed=1)

duration = get_text(page, "#results-table td[class='col-duration']")
assert_that(duration).contains("seconds")

def test_total_number_of_tests_zero(self, pytester):
page = run(pytester)
assert_results(page)
Expand Down

0 comments on commit b7c50c1

Please sign in to comment.