You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Added the new :confval:`consider_namespace_packages` configuration option, defaulting to ``False``.
2
+
3
+
If set to ``True``, pytest will attempt to identify modules that are part of `namespace packages <https://packaging.python.org/en/latest/guides/packaging-namespace-packages>`__ when importing modules.
:ref:`--import-mode=importlib <import-mode-importlib>` now tries to import modules using the standard import mechanism (but still without changing :py:data:`sys.path`), falling back to importing modules directly only if that fails.
2
+
3
+
This means that installed packages will be imported under their canonical name if possible first, for example ``app.core.models``, instead of having the module name always be derived from their path (for example ``.env310.lib.site_packages.app.core.models``).
Copy file name to clipboardExpand all lines: doc/en/explanation/pythonpath.rst
+72-18Lines changed: 72 additions & 18 deletions
Original file line number
Diff line number
Diff line change
@@ -10,19 +10,27 @@ Import modes
10
10
11
11
pytest as a testing framework needs to import test modules and ``conftest.py`` files for execution.
12
12
13
-
Importing files in Python (at least until recently) is a non-trivial processes, often requiring
14
-
changing :data:`sys.path`. Some aspects of the
13
+
Importing files in Python is a non-trivial processes, so aspects of the
15
14
import process can be controlled through the ``--import-mode`` command-line flag, which can assume
16
15
these values:
17
16
17
+
.. _`import-mode-prepend`:
18
+
18
19
* ``prepend`` (default): the directory path containing each module will be inserted into the *beginning*
19
-
of :py:data:`sys.path` if not already there, and then imported with the :func:`importlib.import_module <importlib.import_module>` function.
20
+
of :py:data:`sys.path` if not already there, and then imported with
21
+
the :func:`importlib.import_module <importlib.import_module>` function.
22
+
23
+
It is highly recommended to arrange your test modules as packages by adding ``__init__.py`` files to your directories
24
+
containing tests. This will make the tests part of a proper Python package, allowing pytest to resolve their full
25
+
name (for example ``tests.core.test_core`` for ``test_core.py`` inside the ``tests.core`` package).
20
26
21
-
This requires test module names to be unique when the test directory tree is not arranged in
22
-
packages, because the modules will put in :py:data:`sys.modules` after importing.
27
+
If the test directory tree is not arranged as packages, then each test file needs to have a unique name
28
+
compared to the other test files, otherwise pytest will raise an error if it finds two tests with the same name.
23
29
24
30
This is the classic mechanism, dating back from the time Python 2 was still supported.
25
31
32
+
.. _`import-mode-append`:
33
+
26
34
* ``append``: the directory containing each module is appended to the end of :py:data:`sys.path` if not already
27
35
there, and imported with :func:`importlib.import_module <importlib.import_module>`.
28
36
@@ -38,32 +46,78 @@ these values:
38
46
the tests will run against the installed version
39
47
of ``pkg_under_test`` when ``--import-mode=append`` is used whereas
40
48
with ``prepend`` they would pick up the local version. This kind of confusion is why
41
-
we advocate for using :ref:`src <src-layout>` layouts.
49
+
we advocate for using :ref:`src-layouts<src-layout>`.
42
50
43
51
Same as ``prepend``, requires test module names to be unique when the test directory tree is
44
52
not arranged in packages, because the modules will put in :py:data:`sys.modules` after importing.
45
53
46
-
* ``importlib``: new in pytest-6.0, this mode uses more fine control mechanisms provided by :mod:`importlib` to import test modules. This gives full control over the import process, and doesn't require changing :py:data:`sys.path`.
54
+
.. _`import-mode-importlib`:
55
+
56
+
* ``importlib``: this mode uses more fine control mechanisms provided by :mod:`importlib` to import test modules, without changing :py:data:`sys.path`.
57
+
58
+
Advantages of this mode:
59
+
60
+
* pytest will not change :py:data:`sys.path` at all.
61
+
* Test module names do not need to be unique -- pytest will generate a unique name automatically based on the ``rootdir``.
62
+
63
+
Disadvantages:
64
+
65
+
* Test modules can't import each other.
66
+
* Testing utility modules in the tests directories (for example a ``tests.helpers`` module containing test-related functions/classes)
67
+
are not importable. The recommendation in this case it to place testing utility modules together with the application/library
68
+
code, for example ``app.testing.helpers``.
69
+
70
+
Important: by "test utility modules" we mean functions/classes which are imported by
71
+
other tests directly; this does not include fixtures, which should be placed in ``conftest.py`` files, along
72
+
with the test modules, and are discovered automatically by pytest.
73
+
74
+
It works like this:
75
+
76
+
1. Given a certain module path, for example ``tests/core/test_models.py``, derives a canonical name
77
+
like ``tests.core.test_models`` and tries to import it.
47
78
48
-
For this reason this doesn't require test module names to be unique.
79
+
For non-test modules this will work if they are accessible via :py:data:`sys.path`, so
80
+
for example ``.env/lib/site-packages/app/core.py`` will be importable as ``app.core``.
81
+
This is happens when plugins import non-test modules (for example doctesting).
49
82
50
-
One drawback however is that test modules are non-importable by each other. Also, utility
51
-
modules in the tests directories are not automatically importable because the tests directory is no longer
52
-
added to :py:data:`sys.path`.
83
+
If this step succeeds, the module is returned.
53
84
54
-
Initially we intended to make ``importlib`` the default in future releases, however it is clear now that
55
-
it has its own set of drawbacks so the default will remain ``prepend`` for the foreseeable future.
85
+
For test modules, unless they are reachable from :py:data:`sys.path`, this step will fail.
86
+
87
+
2. If the previous step fails, we import the module directly using ``importlib`` facilities, which lets us import it without
88
+
changing :py:data:`sys.path`.
89
+
90
+
Because Python requires the module to also be available in :py:data:`sys.modules`, pytest derives a unique name for it based
91
+
on its relative location from the ``rootdir``, and adds the module to :py:data:`sys.modules`.
92
+
93
+
For example, ``tests/core/test_models.py`` will end up being imported as the module ``tests.core.test_models``.
94
+
95
+
.. versionadded:: 6.0
96
+
97
+
.. note::
98
+
99
+
Initially we intended to make ``importlib`` the default in future releases, however it is clear now that
100
+
it has its own set of drawbacks so the default will remain ``prepend`` for the foreseeable future.
101
+
102
+
.. note::
103
+
104
+
By default, pytest will not attempt to resolve namespace packages automatically, but that can
105
+
be changed via the :confval:`consider_namespace_packages` configuration variable.
56
106
57
107
.. seealso::
58
108
59
109
The :confval:`pythonpath` configuration variable.
60
110
111
+
The :confval:`consider_namespace_packages` configuration variable.
112
+
113
+
:ref:`test layout`.
114
+
61
115
62
116
``prepend`` and ``append`` import modes scenarios
63
117
-------------------------------------------------
64
118
65
119
Here's a list of scenarios when using ``prepend`` or ``append`` import modes where pytest needs to
66
-
change ``sys.path`` in order to import test modules or ``conftest.py`` files, and the issues users
120
+
change :py:data:`sys.path` in order to import test modules or ``conftest.py`` files, and the issues users
67
121
might encounter because of that.
68
122
69
123
Test modules / ``conftest.py`` files inside packages
@@ -92,7 +146,7 @@ pytest will find ``foo/bar/tests/test_foo.py`` and realize it is part of a packa
92
146
there's an ``__init__.py`` file in the same folder. It will then search upwards until it can find the
93
147
last folder which still contains an ``__init__.py`` file in order to find the package *root* (in
94
148
this case ``foo/``). To load the module, it will insert ``root/`` to the front of
95
-
``sys.path`` (if not there already) in order to load
149
+
:py:data:`sys.path` (if not there already) in order to load
96
150
``test_foo.py`` as the *module* ``foo.bar.tests.test_foo``.
97
151
98
152
The same logic applies to the ``conftest.py`` file: it will be imported as ``foo.conftest`` module.
@@ -122,8 +176,8 @@ When executing:
122
176
123
177
pytest will find ``foo/bar/tests/test_foo.py`` and realize it is NOT part of a package given that
124
178
there's no ``__init__.py`` file in the same folder. It will then add ``root/foo/bar/tests`` to
125
-
``sys.path`` in order to import ``test_foo.py`` as the *module* ``test_foo``. The same is done
126
-
with the ``conftest.py`` file by adding ``root/foo`` to ``sys.path`` to import it as ``conftest``.
179
+
:py:data:`sys.path` in order to import ``test_foo.py`` as the *module* ``test_foo``. The same is done
180
+
with the ``conftest.py`` file by adding ``root/foo`` to :py:data:`sys.path` to import it as ``conftest``.
127
181
128
182
For this reason this layout cannot have test modules with the same name, as they all will be
129
183
imported in the global import namespace.
@@ -136,7 +190,7 @@ Invoking ``pytest`` versus ``python -m pytest``
136
190
-----------------------------------------------
137
191
138
192
Running pytest with ``pytest [...]`` instead of ``python -m pytest [...]`` yields nearly
139
-
equivalent behaviour, except that the latter will add the current directory to ``sys.path``, which
193
+
equivalent behaviour, except that the latter will add the current directory to :py:data:`sys.path`, which
Copy file name to clipboardExpand all lines: doc/en/reference/reference.rst
+13Lines changed: 13 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -1274,6 +1274,19 @@ passed multiple times. The expected format is ``name=value``. For example::
1274
1274
variables, that will be expanded. For more information about cache plugin
1275
1275
please refer to :ref:`cache_provider`.
1276
1276
1277
+
.. confval:: consider_namespace_packages
1278
+
1279
+
Controls if pytest should attempt to identify `namespace packages <https://packaging.python.org/en/latest/guides/packaging-namespace-packages>`__
1280
+
when collecting Python modules. Default is ``False``.
1281
+
1282
+
Set to ``True`` if you are testing namespace packages installed into a virtual environment and it is important for
1283
+
your packages to be imported using their full namespace package name.
1284
+
1285
+
Only `native namespace packages <https://packaging.python.org/en/latest/guides/packaging-namespace-packages/#native-namespace-packages>`__
1286
+
are supported, with no plans to support `legacy namespace packages <https://packaging.python.org/en/latest/guides/packaging-namespace-packages/#legacy-namespace-packages>`__.
1287
+
1288
+
.. versionadded:: 8.1
1289
+
1277
1290
.. confval:: console_output_style
1278
1291
1279
1292
Sets the console output style while running tests:
0 commit comments