Repository navigation
Add --reruns-on-exitfirst to override rerun count under -x/--maxfail #377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Add ``--reruns-on-exitfirst`` option to use a different rerun count when | ||
| ``-x``/``--exitfirst`` or ``--maxfail`` is given, e.g. ``--reruns-on-exitfirst | ||
| 0`` to skip reruns entirely when exiting on the first failure. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -178,6 +178,15 @@ def pytest_addoption(parser): | |
| "'rerun test summary info' section, which is emitted automatically " | ||
| "when this flag is set.", | ||
| ) | ||
| group._addoption( | ||
| "--reruns-on-exitfirst", | ||
| action="store", | ||
| dest="reruns_on_exitfirst", | ||
| type=int, | ||
| help="Number of reruns to use when -x/--exitfirst or --maxfail is " | ||
| "given. Defaults to the regular rerun settings. Use " | ||
| "--reruns-on-exitfirst 0 to skip reruns entirely when exiting early.", | ||
| ) | ||
|
Comment on lines
+181
to
+189
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. — Comment created by Claude No ini counterpart. |
||
| group.addoption( | ||
| "--max-suite-reruns", | ||
| action="store", | ||
|
|
@@ -226,7 +235,16 @@ def check_options(config): | |
| and config.option.max_suite_reruns < 0 | ||
| ): | ||
| raise pytest.UsageError("--max-suite-reruns must be >= 0") | ||
| if ( | ||
| config.option.reruns_on_exitfirst is not None | ||
| and config.option.reruns_on_exitfirst < 0 | ||
| ): | ||
| raise pytest.UsageError("--reruns-on-exitfirst must be >= 0") | ||
| reruns = config.getoption("force_reruns") or _get_global_reruns(config) | ||
| if not reruns and config.option.maxfail: | ||
| # --reruns-on-exitfirst takes effect under -x/--maxfail even when | ||
| # no other rerun count is configured | ||
| reruns = config.getoption("reruns_on_exitfirst") | ||
|
Comment on lines
243
to
+247
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. — Comment created by Claude Precedence here does not match |
||
| if not config.getoption("collectonly") and reruns: | ||
| if config.option.usepdb: # a core option | ||
| raise pytest.UsageError("--reruns incompatible with --pdb") | ||
|
|
@@ -250,6 +268,13 @@ def get_reruns_count(item): | |
| if reruns is not None: | ||
| return reruns | ||
|
|
||
| if item.session.config.option.maxfail: | ||
| reruns = item.session.config.getoption("reruns_on_exitfirst") | ||
| if reruns is not None: | ||
| # -x/--exitfirst or --maxfail given: override marker and global | ||
| # rerun counts so the run can exit on the first real failure. | ||
| return reruns | ||
|
Comment on lines
+271
to
+276
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. — Comment created by Claude
Comment on lines
+271
to
+276
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. — Comment created by Claude Turns on reruns for every test when no rerun setting exists. With only |
||
|
|
||
| rerun_marker = _get_marker(item) | ||
| # use the marker as a priority over the global setting. | ||
| if rerun_marker is not None: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -548,6 +548,70 @@ def test_pass(): | |
| assert_outcomes(result, passed=1, rerun=2) | ||
|
|
||
|
|
||
| def test_reruns_on_exitfirst_zero_disables_reruns(testdir): | ||
| testdir.makepyfile("def test_fail(): assert False") | ||
| result = testdir.runpytest("--reruns", "2", "-x", "--reruns-on-exitfirst", "0") | ||
| assert_outcomes(result, passed=0, failed=1, rerun=0) | ||
|
|
||
|
|
||
| def test_reruns_on_exitfirst_overrides_flaky_marker(testdir): | ||
| testdir.makepyfile( | ||
| f""" | ||
| import pytest | ||
| @pytest.mark.flaky(reruns=2) | ||
| def test_fail(): | ||
| {temporary_failure()}""" | ||
| ) | ||
| result = testdir.runpytest("-x", "--reruns-on-exitfirst", "0") | ||
| assert_outcomes(result, passed=0, failed=1, rerun=0) | ||
|
|
||
|
|
||
| def test_reruns_on_exitfirst_limits_reruns(testdir): | ||
| testdir.makepyfile( | ||
| f""" | ||
| def test_fail(): | ||
| {temporary_failure(3)}""" | ||
| ) | ||
| result = testdir.runpytest("--reruns", "3", "-x", "--reruns-on-exitfirst", "1") | ||
| assert_outcomes(result, passed=0, failed=1, rerun=1) | ||
|
|
||
|
|
||
| def test_reruns_on_exitfirst_applies_to_maxfail(testdir): | ||
| testdir.makepyfile("def test_fail(): assert False") | ||
| result = testdir.runpytest( | ||
| "--reruns", "2", "--maxfail", "2", "--reruns-on-exitfirst", "0" | ||
| ) | ||
| assert_outcomes(result, passed=0, failed=1, rerun=0) | ||
|
Comment on lines
+579
to
+584
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. — Comment created by Claude Test does not exercise |
||
|
|
||
|
|
||
| def test_exitfirst_without_reruns_on_exitfirst_still_reruns(testdir): | ||
| testdir.makepyfile( | ||
| f""" | ||
| def test_fail(): | ||
| {temporary_failure(2)}""" | ||
| ) | ||
| result = testdir.runpytest("--reruns", "2", "-x") | ||
| assert_outcomes(result, passed=1, rerun=2) | ||
|
|
||
|
|
||
| def test_reruns_on_exitfirst_negative_rejected(testdir): | ||
| testdir.makepyfile("def test_pass(): pass") | ||
| result = testdir.runpytest("-x", "--reruns-on-exitfirst", "-1") | ||
| result.stderr.fnmatch_lines_random("ERROR: --reruns-on-exitfirst must be >= 0") | ||
|
|
||
|
|
||
| def test_error_when_run_with_pdb_and_reruns_on_exitfirst(testdir): | ||
| testdir.makepyfile("def test_pass(): pass") | ||
| result = testdir.runpytest("-x", "--reruns-on-exitfirst", "1", "--pdb") | ||
| result.stderr.fnmatch_lines_random("ERROR: --reruns incompatible with --pdb") | ||
|
Comment on lines
+603
to
+606
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. — Comment created by Claude Conflicts with master; this test will fail after the merge. Master (#374) changed |
||
|
|
||
|
|
||
| def test_no_error_when_run_with_pdb_and_zero_reruns_on_exitfirst(testdir): | ||
| testdir.makepyfile("def test_pass(): pass") | ||
| result = testdir.runpytest("-x", "--reruns-on-exitfirst", "0", "--pdb") | ||
| assert_outcomes(result) | ||
|
|
||
|
|
||
| def test_no_extra_test_summary_for_reruns_by_default(testdir): | ||
| testdir.makepyfile( | ||
| f""" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
— Comment created by Claude
Silently ignored without
-x/--maxfail.pytest --reruns 2 --reruns-on-exitfirst 0without-xdoes nothing and gives no feedback, so a user who expects it to work (e.g.-xset viaaddoptsin one environment only) never notices. Consider a warning when the option is given butmaxfailis 0.