Skip to content

Commit f0a4a13

Browse files
authored
Merge pull request #5333 from blueyed/fix-lf
Fix regression with --lf and non-selected failures
2 parents 5c5966f + ff80464 commit f0a4a13

File tree

3 files changed

+63
-25
lines changed

3 files changed

+63
-25
lines changed

changelog/5333.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix regression with ``--lf`` not re-running all tests with known failures from non-selected tests.

src/_pytest/cacheprovider.py

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -164,28 +164,27 @@ def __init__(self, config):
164164
def last_failed_paths(self):
165165
"""Returns a set with all Paths()s of the previously failed nodeids (cached).
166166
"""
167-
result = getattr(self, "_last_failed_paths", None)
168-
if result is None:
167+
try:
168+
return self._last_failed_paths
169+
except AttributeError:
169170
rootpath = Path(self.config.rootdir)
170171
result = {rootpath / nodeid.split("::")[0] for nodeid in self.lastfailed}
172+
result = {x for x in result if x.exists()}
171173
self._last_failed_paths = result
172-
return result
174+
return result
173175

174176
def pytest_ignore_collect(self, path):
175177
"""
176178
Ignore this file path if we are in --lf mode and it is not in the list of
177179
previously failed files.
178180
"""
179-
if (
180-
self.active
181-
and self.config.getoption("lf")
182-
and path.isfile()
183-
and self.lastfailed
184-
):
185-
skip_it = Path(path) not in self.last_failed_paths()
186-
if skip_it:
187-
self._skipped_files += 1
188-
return skip_it
181+
if self.active and self.config.getoption("lf") and path.isfile():
182+
last_failed_paths = self.last_failed_paths()
183+
if last_failed_paths:
184+
skip_it = Path(path) not in self.last_failed_paths()
185+
if skip_it:
186+
self._skipped_files += 1
187+
return skip_it
189188

190189
def pytest_report_collectionfinish(self):
191190
if self.active and self.config.getoption("verbose") >= 0:
@@ -234,19 +233,15 @@ def pytest_collection_modifyitems(self, session, config, items):
234233
items[:] = previously_failed + previously_passed
235234

236235
noun = "failure" if self._previously_failed_count == 1 else "failures"
237-
if self._skipped_files > 0:
238-
files_noun = "file" if self._skipped_files == 1 else "files"
239-
skipped_files_msg = " (skipped {files} {files_noun})".format(
240-
files=self._skipped_files, files_noun=files_noun
241-
)
242-
else:
243-
skipped_files_msg = ""
244236
suffix = " first" if self.config.getoption("failedfirst") else ""
245-
self._report_status = "rerun previous {count} {noun}{suffix}{skipped_files}".format(
246-
count=self._previously_failed_count,
247-
suffix=suffix,
248-
noun=noun,
249-
skipped_files=skipped_files_msg,
237+
self._report_status = "rerun previous {count} {noun}{suffix}".format(
238+
count=self._previously_failed_count, suffix=suffix, noun=noun
239+
)
240+
241+
if self._skipped_files > 0:
242+
files_noun = "file" if self._skipped_files == 1 else "files"
243+
self._report_status += " (skipped {files} {files_noun})".format(
244+
files=self._skipped_files, files_noun=files_noun
250245
)
251246
else:
252247
self._report_status = "no previously failed tests, "

testing/test_cacheprovider.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,48 @@ def test_3(): pass
832832
]
833833
)
834834

835+
def test_lastfailed_with_known_failures_not_being_selected(self, testdir):
836+
testdir.makepyfile(
837+
**{
838+
"pkg1/test_1.py": """def test_1(): assert 0""",
839+
"pkg1/test_2.py": """def test_2(): pass""",
840+
}
841+
)
842+
result = testdir.runpytest()
843+
result.stdout.fnmatch_lines(["collected 2 items", "* 1 failed, 1 passed in *"])
844+
845+
py.path.local("pkg1/test_1.py").remove()
846+
result = testdir.runpytest("--lf")
847+
result.stdout.fnmatch_lines(
848+
[
849+
"collected 1 item",
850+
"run-last-failure: 1 known failures not in selected tests",
851+
"* 1 passed in *",
852+
]
853+
)
854+
855+
# Recreate file with known failure.
856+
testdir.makepyfile(**{"pkg1/test_1.py": """def test_1(): assert 0"""})
857+
result = testdir.runpytest("--lf")
858+
result.stdout.fnmatch_lines(
859+
[
860+
"collected 1 item",
861+
"run-last-failure: rerun previous 1 failure (skipped 1 file)",
862+
"* 1 failed in *",
863+
]
864+
)
865+
866+
# Remove/rename test.
867+
testdir.makepyfile(**{"pkg1/test_1.py": """def test_renamed(): assert 0"""})
868+
result = testdir.runpytest("--lf")
869+
result.stdout.fnmatch_lines(
870+
[
871+
"collected 1 item",
872+
"run-last-failure: 1 known failures not in selected tests (skipped 1 file)",
873+
"* 1 failed in *",
874+
]
875+
)
876+
835877

836878
class TestNewFirst(object):
837879
def test_newfirst_usecase(self, testdir):

0 commit comments

Comments
 (0)