-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12810 from FreerGit/dont-auto-discover-feat
Add `discover_imports` in conf, don't collect imported classes named Test* closes #12749`
- Loading branch information
Showing
6 changed files
with
172 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
pytest traditionally collects classes/functions in the test module namespace even if they are imported from another file. | ||
|
||
For example: | ||
|
||
.. code-block:: python | ||
# contents of src/domain.py | ||
class Testament: ... | ||
# contents of tests/test_testament.py | ||
from domain import Testament | ||
def test_testament(): ... | ||
In this scenario with the default options, pytest will collect the class `Testament` from `tests/test_testament.py` because it starts with `Test`, even though in this case it is a production class being imported in the test module namespace. | ||
|
||
This behavior can now be prevented by setting the new :confval:`collect_imported_tests` configuration option to ``false``, which will make pytest collect classes/functions from test files **only** if they are defined in that file. | ||
|
||
-- by :user:`FreerGit` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
"""Tests for the `collect_imported_tests` configuration value.""" | ||
|
||
from __future__ import annotations | ||
|
||
import textwrap | ||
|
||
from _pytest.pytester import Pytester | ||
import pytest | ||
|
||
|
||
def setup_files(pytester: Pytester) -> None: | ||
src_dir = pytester.mkdir("src") | ||
tests_dir = pytester.mkdir("tests") | ||
src_file = src_dir / "foo.py" | ||
|
||
src_file.write_text( | ||
textwrap.dedent("""\ | ||
class Testament: | ||
def test_collections(self): | ||
pass | ||
def test_testament(): pass | ||
"""), | ||
encoding="utf-8", | ||
) | ||
|
||
test_file = tests_dir / "foo_test.py" | ||
test_file.write_text( | ||
textwrap.dedent("""\ | ||
from foo import Testament, test_testament | ||
class TestDomain: | ||
def test(self): | ||
testament = Testament() | ||
assert testament | ||
"""), | ||
encoding="utf-8", | ||
) | ||
|
||
pytester.syspathinsert(src_dir) | ||
|
||
|
||
def test_collect_imports_disabled(pytester: Pytester) -> None: | ||
""" | ||
When collect_imported_tests is disabled, only objects in the | ||
test modules are collected as tests, so the imported names (`Testament` and `test_testament`) | ||
are not collected. | ||
""" | ||
pytester.makeini( | ||
""" | ||
[pytest] | ||
collect_imported_tests = false | ||
""" | ||
) | ||
|
||
setup_files(pytester) | ||
result = pytester.runpytest("-v", "tests") | ||
result.stdout.fnmatch_lines( | ||
[ | ||
"tests/foo_test.py::TestDomain::test PASSED*", | ||
] | ||
) | ||
|
||
# Ensure that the hooks were only called for the collected item. | ||
reprec = result.reprec # type:ignore[attr-defined] | ||
reports = reprec.getreports("pytest_collectreport") | ||
[modified] = reprec.getcalls("pytest_collection_modifyitems") | ||
[item_collected] = reprec.getcalls("pytest_itemcollected") | ||
|
||
assert [x.nodeid for x in reports] == [ | ||
"", | ||
"tests/foo_test.py::TestDomain", | ||
"tests/foo_test.py", | ||
"tests", | ||
] | ||
assert [x.nodeid for x in modified.items] == ["tests/foo_test.py::TestDomain::test"] | ||
assert item_collected.item.nodeid == "tests/foo_test.py::TestDomain::test" | ||
|
||
|
||
@pytest.mark.parametrize("configure_ini", [False, True]) | ||
def test_collect_imports_enabled(pytester: Pytester, configure_ini: bool) -> None: | ||
""" | ||
When collect_imported_tests is enabled (the default), all names in the | ||
test modules are collected as tests. | ||
""" | ||
if configure_ini: | ||
pytester.makeini( | ||
""" | ||
[pytest] | ||
collect_imported_tests = true | ||
""" | ||
) | ||
|
||
setup_files(pytester) | ||
result = pytester.runpytest("-v", "tests") | ||
result.stdout.fnmatch_lines( | ||
[ | ||
"tests/foo_test.py::Testament::test_collections PASSED*", | ||
"tests/foo_test.py::test_testament PASSED*", | ||
"tests/foo_test.py::TestDomain::test PASSED*", | ||
] | ||
) |