Skip to content

Commit b7c50c1

Browse files
authored
Feat: Add duration format hook (#724)
1 parent 372acd8 commit b7c50c1

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-2
lines changed

docs/user_guide.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,28 @@ Note that the values are case *sensitive*.
304304
If tests are run in parallel (with `pytest-xdist`_ for example), then the order may not be
305305
in the correct order.
306306

307+
Formatting the Duration Column
308+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
309+
310+
The formatting of the timestamp used in the :code:`Durations` column can be modified by using the
311+
:code:`pytest_html_duration_format` hook. The default timestamp will be `nnn ms` for durations
312+
less than one second and `hh:mm:ss` for durations equal to or greater than one second.
313+
314+
Below is an example of a :code:`conftest.py` file setting :code:`pytest_html_duration_format`:
315+
316+
.. code-block:: python
317+
318+
import datetime
319+
320+
321+
def pytest_html_duration_format(duration):
322+
duration_timedelta = datetime.timedelta(seconds=duration)
323+
time = datetime.datetime(1, 1, 1) + duration_timedelta
324+
return time.strftime("%H:%M:%S")
325+
326+
**NOTE**: The behavior of sorting the duration column is not guaranteed when providing a custom format.
327+
328+
**NOTE**: The formatting of the total duration is not affected by this hook.
307329

308330
.. _@pytest.hookimpl(tryfirst=True): https://docs.pytest.org/en/stable/writing_plugins.html#hook-function-ordering-call-example
309331
.. _ansi2html: https://pypi.python.org/pypi/ansi2html/

src/pytest_html/basereport.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,19 @@ def pytest_collection_finish(self, session):
197197
def pytest_runtest_logreport(self, report):
198198
if hasattr(report, "duration_formatter"):
199199
warnings.warn(
200-
"'duration_formatter' has been removed and no longer has any effect!",
200+
"'duration_formatter' has been removed and no longer has any effect!"
201+
"Please use the 'pytest_html_duration_format' hook instead.",
201202
DeprecationWarning,
202203
)
203204

204205
outcome = _process_outcome(report)
205-
duration = _format_duration(report.duration)
206+
try:
207+
# hook returns as list for some reason
208+
duration = self._config.hook.pytest_html_duration_format(
209+
duration=report.duration
210+
)[0]
211+
except IndexError:
212+
duration = _format_duration(report.duration)
206213
self._report.total_duration += report.duration
207214

208215
test_id = report.nodeid

src/pytest_html/hooks.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ def pytest_html_results_table_row(report, cells):
2121

2222
def pytest_html_results_table_html(report, data):
2323
"""Called after building results table additional HTML."""
24+
25+
26+
def pytest_html_duration_format(duration):
27+
"""Called before using the default duration formatting."""

testing/test_integration.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,21 @@ def test_sleep():
156156
assert_that(duration).matches(expectation)
157157
assert_that(total_duration).matches(r"\d{2}:\d{2}:\d{2}")
158158

159+
def test_duration_format_hook(self, pytester):
160+
pytester.makeconftest(
161+
"""
162+
def pytest_html_duration_format(duration):
163+
return str(round(duration * 1000)) + " seconds"
164+
"""
165+
)
166+
167+
pytester.makepyfile("def test_pass(): pass")
168+
page = run(pytester)
169+
assert_results(page, passed=1)
170+
171+
duration = get_text(page, "#results-table td[class='col-duration']")
172+
assert_that(duration).contains("seconds")
173+
159174
def test_total_number_of_tests_zero(self, pytester):
160175
page = run(pytester)
161176
assert_results(page)

0 commit comments

Comments
 (0)