Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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 AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ Stefanie Molin
Stefano Taschini
Steffen Allner
Stephan Obermann
Sven
Sven-Hendrik Haase
Sviatoslav Sydorenko
Sylvain Marié
Expand Down
5 changes: 5 additions & 0 deletions changelog/12749.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
New :confval:`collect_imported_tests`: when enabled (the default) pytest will collect classes/functions in test modules even if they are imported from another file.

Setting this to False will make pytest collect classes/functions from test files only if they are defined in that file (as opposed to imported there).

-- by :user:`FreerGit`
17 changes: 14 additions & 3 deletions doc/en/reference/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,20 @@ passed multiple times. The expected format is ``name=value``. For example::
variables, that will be expanded. For more information about cache plugin
please refer to :ref:`cache_provider`.

.. confval:: collect_imported_tests

.. versionadded:: 8.4

Setting this to ``false`` will make pytest collect classes/functions from test
files only if they are defined in that file (as opposed to imported there).

.. code-block:: ini

[pytest]
collect_imported_tests = false

Default: ``true``

.. confval:: consider_namespace_packages

Controls if pytest should attempt to identify `namespace packages <https://packaging.python.org/en/latest/guides/packaging-namespace-packages>`__
Expand Down Expand Up @@ -1838,11 +1852,8 @@ passed multiple times. The expected format is ``name=value``. For example::

pytest testing doc


.. confval:: tmp_path_retention_count



How many sessions should we keep the `tmp_path` directories,
according to `tmp_path_retention_policy`.

Expand Down
6 changes: 6 additions & 0 deletions src/_pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ def pytest_addoption(parser: Parser) -> None:
type="args",
default=[],
)
parser.addini(
"collect_imported_tests",
"Whether to collect tests in imported modules outside `testpaths`",
type="bool",
default=True,
)
group = parser.getgroup("general", "Running and selection options")
group._addoption(
"-x",
Expand Down
19 changes: 19 additions & 0 deletions src/_pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,15 @@
if name in seen:
continue
seen.add(name)

if not self.session.config.getini("collect_imported_tests"):
# Do not collect imported functions
if inspect.isfunction(obj) and isinstance(self, Module):

Check warning on line 422 in src/_pytest/python.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/python.py#L421-L422

Added lines #L421 - L422 were not covered by tests
fn_defined_at = obj.__module__
in_module = self._getobj().__name__

Check warning on line 424 in src/_pytest/python.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/python.py#L424

Added line #L424 was not covered by tests
if fn_defined_at != in_module:
continue

res = ihook.pytest_pycollect_makeitem(
collector=self, name=name, obj=obj
)
Expand Down Expand Up @@ -741,6 +750,16 @@
return self.obj()

def collect(self) -> Iterable[nodes.Item | nodes.Collector]:
if not self.config.getini("collect_imported_tests"):
# This entire branch will discard (not collect) a class
# if it is imported (defined in a different module)
if isinstance(self, Class) and isinstance(self.parent, Module):
if inspect.isclass(self._getobj()):

Check warning on line 757 in src/_pytest/python.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/python.py#L756-L757

Added lines #L756 - L757 were not covered by tests
class_defined_at = self._getobj().__module__
in_module = self.parent._getobj().__name__

Check warning on line 759 in src/_pytest/python.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/python.py#L759

Added line #L759 was not covered by tests
if class_defined_at != in_module:
return []

Check warning on line 762 in src/_pytest/python.py

View check run for this annotation

Codecov / codecov/patch

src/_pytest/python.py#L762

Added line #L762 was not covered by tests
if not safe_getattr(self.obj, "__test__", True):
return []
if hasinit(self.obj):
Expand Down
Loading
Loading