diff --git a/changelog/7758.bugfix.rst b/changelog/7758.bugfix.rst new file mode 100644 index 000000000..a3119b46c --- /dev/null +++ b/changelog/7758.bugfix.rst @@ -0,0 +1 @@ +Fixed an issue where some files in packages are getting lost from ``--lf`` even though they contain tests that failed. Regressed in pytest 5.4.0. diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 20f0c71d3..09f3d6653 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -28,6 +28,7 @@ from _pytest.config.argparsing import Parser from _pytest.fixtures import FixtureRequest from _pytest.main import Session from _pytest.python import Module +from _pytest.python import Package from _pytest.reports import TestReport @@ -232,7 +233,10 @@ class LFPluginCollSkipfiles: def pytest_make_collect_report( self, collector: nodes.Collector ) -> Optional[CollectReport]: - if isinstance(collector, Module): + # Packages are Modules, but _last_failed_paths only contains + # test-bearing paths and doesn't try to include the paths of their + # packages, so don't filter them. + if isinstance(collector, Module) and not isinstance(collector, Package): if Path(str(collector.fspath)) not in self.lfplugin._last_failed_paths: self.lfplugin._skipped_files += 1 diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 6203ebec7..54e657b27 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -7,6 +7,7 @@ import py import pytest from _pytest.config import ExitCode +from _pytest.pytester import Pytester from _pytest.pytester import Testdir pytest_plugins = ("pytester",) @@ -982,6 +983,36 @@ class TestLastFailed: ) assert result.ret == 0 + def test_packages(self, pytester: Pytester) -> None: + """Regression test for #7758. + + The particular issue here was that Package nodes were included in the + filtering, being themselves Modules for the __init__.py, even if they + had failed Modules in them. + + The tests includes a test in an __init__.py file just to make sure the + fix doesn't somehow regress that, it is not critical for the issue. + """ + pytester.makepyfile( + **{ + "__init__.py": "", + "a/__init__.py": "def test_a_init(): assert False", + "a/test_one.py": "def test_1(): assert False", + "b/__init__.py": "", + "b/test_two.py": "def test_2(): assert False", + }, + ) + pytester.makeini( + """ + [pytest] + python_files = *.py + """ + ) + result = pytester.runpytest() + result.assert_outcomes(failed=3) + result = pytester.runpytest("--lf") + result.assert_outcomes(failed=3) + class TestNewFirst: def test_newfirst_usecase(self, testdir):