Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ Changelog
16.3 (unreleased)
-----------------

- Nothing changed yet.
Features
++++++++

- Add ``--rerun-show-tracebacks`` option to display tracebacks from failed
attempts that were retried, including tests that eventually passed. The
rerun summary section is emitted automatically when the flag is set, so
``-rR`` is no longer required to see the tracebacks.
Fixes `#156 <https://github.com/pytest-dev/pytest-rerunfailures/issues/156>`_.


16.2 (2026-05-13)
Expand Down
16 changes: 16 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,22 @@ of re-runs specified in test markers, pass ``--force-reruns``:

$ pytest --force-reruns 5

Show tracebacks for retried failures
------------------------------------

By default only the *final* attempt of a flaky test produces a traceback,
so failures from earlier attempts (including those of tests that ultimately
pass after a rerun) are silently discarded. To inspect them, pass
``--rerun-show-tracebacks``:

.. code-block:: bash

$ pytest --reruns 2 --rerun-show-tracebacks

Each retried attempt's traceback is appended to the ``rerun test summary
info`` section. The section is emitted automatically when the flag is set,
so ``-rR`` is not required.

Output
------

Expand Down
31 changes: 19 additions & 12 deletions src/pytest_rerunfailures.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ def pytest_addoption(parser):
dest="fail_on_flaky",
help="Fail the test run with exit code 7 if a flaky test passes on a rerun.",
)
group._addoption(
"--rerun-show-tracebacks",
action="store_true",
dest="rerun_show_tracebacks",
help="Show tracebacks for failed attempts that were retried, including "
"tests that eventually passed. Tracebacks are appended to the "
"'rerun test summary info' section, which is emitted automatically "
"when this flag is set.",
)

arg_type = "string"
parser.addini("reruns", RERUNS_DESC, type=arg_type)
Expand Down Expand Up @@ -636,26 +645,24 @@ def pytest_report_teststatus(report):
def pytest_terminal_summary(terminalreporter):
# Adapted from https://pytest.org/latest/_modules/_pytest/skipping.html
tr = terminalreporter
if not tr.reportchars:
show_tracebacks = tr.config.getoption("rerun_show_tracebacks", False)
if not show_tracebacks and not any(c in "rR" for c in tr.reportchars):
return

lines = []
for char in tr.reportchars:
if char in "rR":
show_rerun(terminalreporter, lines)

lines = show_rerun(terminalreporter, show_tracebacks=show_tracebacks)
if lines:
tr._tw.sep("=", "rerun test summary info")
for line in lines:
tr._tw.line(line)


def show_rerun(terminalreporter, lines):
rerun = terminalreporter.stats.get("rerun")
if rerun:
for rep in rerun:
pos = rep.nodeid
lines.append(f"RERUN {pos}")
def show_rerun(terminalreporter, show_tracebacks=False):
lines = []
for rep in terminalreporter.stats.get("rerun", []):
lines.append(f"RERUN {rep.nodeid}")
if show_tracebacks and rep.longrepr:
lines.extend(str(rep.longrepr).splitlines())
return lines


@pytest.hookimpl(trylast=True)
Expand Down
41 changes: 41 additions & 0 deletions tests/test_pytest_rerunfailures.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,47 @@ def test_pass():
assert "1 rerun" in result.stdout.str()


def test_rerun_show_tracebacks_for_eventual_pass(testdir):
testdir.makepyfile(
f"""
def test_eventually_passes():
{temporary_failure()}"""
)
result = testdir.runpytest("--reruns", "1", "--rerun-show-tracebacks")
assert result.ret == 0
stdout = result.stdout.str()
assert "rerun test summary info" in stdout
assert "RERUN test_rerun_show_tracebacks_for_eventual_pass" in stdout
assert "Exception: Failure: 1" in stdout
assert "1 passed" in stdout
assert "1 rerun" in stdout


def test_rerun_show_tracebacks_off_by_default(testdir):
testdir.makepyfile(
f"""
def test_eventually_passes():
{temporary_failure()}"""
)
result = testdir.runpytest("--reruns", "1")
stdout = result.stdout.str()
assert "rerun test summary info" not in stdout
assert "Exception: Failure" not in stdout


def test_rerun_show_tracebacks_with_reportchars(testdir):
testdir.makepyfile(
f"""
def test_eventually_passes():
{temporary_failure()}"""
)
result = testdir.runpytest("--reruns", "1", "--rerun-show-tracebacks", "-rR")
stdout = result.stdout.str()
# Only one rerun summary section, not duplicated by the -rR path.
assert stdout.count("rerun test summary info") == 1
assert "Exception: Failure: 1" in stdout


def test_verbose(testdir):
testdir.makepyfile(
f"""
Expand Down
Loading