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
1 change: 1 addition & 0 deletions changes/342.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a regression in version 16.5 which made ``--pdb`` unusable even when no reruns were configured.
34 changes: 20 additions & 14 deletions src/pytest_rerunfailures.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,16 @@ def pytest_addoption(parser):
)


def _get_global_reruns(config):
reruns = config.getvalue("reruns")
if reruns is not None:
return reruns

with suppress(TypeError, ValueError):
reruns = int(config.getini("reruns"))
return reruns


# making sure the options make sense
# should run before / at the beginning of pytest_cmdline_main
def check_options(config):
Expand All @@ -187,7 +197,8 @@ def check_options(config):
and config.option.max_suite_reruns < 0
):
raise pytest.UsageError("--max-suite-reruns must be >= 0")
if not val("collectonly") and config.option.reruns != 0:
reruns = config.getvalue("force_reruns") or _get_global_reruns(config)
if not val("collectonly") and reruns:
if config.option.usepdb: # a core option
raise pytest.UsageError("--reruns incompatible with --pdb")

Expand All @@ -196,17 +207,6 @@ def _get_marker(item):
return item.get_closest_marker("flaky")


def _get_global_reruns(item):
reruns = item.session.config.getvalue("reruns")
if reruns is not None:
return reruns

reruns = None
with suppress(TypeError, ValueError):
reruns = int(item.session.config.getini("reruns"))
return reruns


def get_reruns_count(item):
reruns = item.session.config.getvalue("force_reruns")
if reruns is not None:
Expand All @@ -225,12 +225,12 @@ def get_reruns_count(item):
marker_reruns = 1

if item.session.config.getvalue("reruns_mode") == "append":
global_reruns = _get_global_reruns(item)
global_reruns = _get_global_reruns(item.session.config)
if global_reruns is not None:
return marker_reruns + global_reruns
return marker_reruns

return _get_global_reruns(item)
return _get_global_reruns(item.session.config)


def get_reruns_delay(item):
Expand Down Expand Up @@ -945,6 +945,12 @@ def pytest_runtest_protocol(item, nextitem):
# flaky
return

if reruns and item.session.config.option.usepdb:
# the global options are already rejected in check_options(); this
# catches reruns requested via the flaky marker, which are only
# known once the item is available
raise pytest.UsageError("--reruns incompatible with --pdb")

delay = get_reruns_delay(item)
delay_backoff_factor = get_reruns_delay_backoff_factor(item)
parallel = not is_master(item.config)
Expand Down
38 changes: 38 additions & 0 deletions tests/test_pytest_rerunfailures.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,44 @@ def test_error_when_run_with_pdb(testdir):
result.stderr.fnmatch_lines_random("ERROR: --reruns incompatible with --pdb")


def test_no_error_when_run_with_pdb_without_reruns(testdir):
testdir.makepyfile("def test_pass(): pass")
result = testdir.runpytest("--pdb")
assert_outcomes(result)


def test_no_error_when_run_with_pdb_and_zero_reruns(testdir):
testdir.makepyfile("def test_pass(): pass")
result = testdir.runpytest("--reruns", "0", "--pdb")
assert_outcomes(result)


def test_error_when_run_with_pdb_and_reruns_ini(testdir):
testdir.makepyfile("def test_pass(): pass")
testdir.makeini("[pytest]\nreruns = 1\n")
result = testdir.runpytest("--pdb")
result.stderr.fnmatch_lines_random("ERROR: --reruns incompatible with --pdb")


def test_error_when_run_with_pdb_and_force_reruns(testdir):
testdir.makepyfile("def test_pass(): pass")
result = testdir.runpytest("--force-reruns", "1", "--pdb")
result.stderr.fnmatch_lines_random("ERROR: --reruns incompatible with --pdb")


def test_error_when_run_with_pdb_and_flaky_marker(testdir):
testdir.makepyfile(
"""
import pytest

@pytest.mark.flaky(reruns=1)
def test_pass(): pass
"""
)
result = testdir.runpytest("--pdb")
result.stderr.fnmatch_lines_random("*--reruns incompatible with --pdb")


def test_no_rerun_on_pass(testdir):
testdir.makepyfile("def test_pass(): pass")
result = testdir.runpytest("--reruns", "1")
Expand Down
Loading