Clarify PYTHONPATH changes and ``rootdir`` roles
- Also minor adjustments in the docs (wording, formatting, links, etc). Fix #2589
This commit is contained in:
parent
c92760dca8
commit
3d24485cae
|
@ -1079,7 +1079,6 @@ class Config(object):
|
|||
self.pluginmanager.load_setuptools_entrypoints('pytest11')
|
||||
self.pluginmanager.consider_env()
|
||||
self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy())
|
||||
confcutdir = self.known_args_namespace.confcutdir
|
||||
if self.known_args_namespace.confcutdir is None and self.inifile:
|
||||
confcutdir = py.path.local(self.inifile).dirname
|
||||
self.known_args_namespace.confcutdir = confcutdir
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
.. _cache:
|
||||
|
||||
Cache: working with cross-testrun state
|
||||
=======================================
|
||||
|
||||
|
|
|
@ -31,9 +31,10 @@ Full pytest documentation
|
|||
plugins
|
||||
writing_plugins
|
||||
|
||||
example/index
|
||||
goodpractices
|
||||
pythonpath
|
||||
customize
|
||||
example/index
|
||||
bash-completion
|
||||
|
||||
backwards-compatibility
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Basic test configuration
|
||||
===================================
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Command line options and configuration file settings
|
||||
-----------------------------------------------------------------
|
||||
|
@ -15,17 +15,31 @@ which were registered by installed plugins.
|
|||
.. _rootdir:
|
||||
.. _inifiles:
|
||||
|
||||
initialization: determining rootdir and inifile
|
||||
Initialization: determining rootdir and inifile
|
||||
-----------------------------------------------
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
pytest determines a "rootdir" for each test run which depends on
|
||||
pytest determines a ``rootdir`` for each test run which depends on
|
||||
the command line arguments (specified test files, paths) and on
|
||||
the existence of inifiles. The determined rootdir and ini-file are
|
||||
printed as part of the pytest header. The rootdir is used for constructing
|
||||
"nodeids" during collection and may also be used by plugins to store
|
||||
project/testrun-specific information.
|
||||
the existence of *ini-files*. The determined ``rootdir`` and *ini-file* are
|
||||
printed as part of the pytest header during startup.
|
||||
|
||||
Here's a summary what ``pytest`` uses ``rootdir`` for:
|
||||
|
||||
* Construct *nodeids* during collection; each test is assigned
|
||||
a unique *nodeid* which is rooted at the ``rootdir`` and takes in account full path,
|
||||
class name, function name and parametrization (if any).
|
||||
|
||||
* Is used by plugins as a stable location to store project/test run specific information;
|
||||
for example, the internal :ref:`cache <cache>` plugin creates a ``.cache`` subdirectory
|
||||
in ``rootdir`` to store its cross-test run state.
|
||||
|
||||
Important to emphasize that ``rootdir`` is **NOT** used to modify ``sys.path``/``PYTHONPATH`` or
|
||||
influence how modules are imported. See :ref:`pythonpath` for more details.
|
||||
|
||||
Finding the ``rootdir``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Here is the algorithm which finds the rootdir from ``args``:
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
.. _examples:
|
||||
|
||||
Usages and Examples
|
||||
===========================================
|
||||
Examples and customization tricks
|
||||
=================================
|
||||
|
||||
Here is a (growing) list of examples. :ref:`Contact <contact>` us if you
|
||||
need more examples or have questions. Also take a look at the
|
||||
|
|
|
@ -26,7 +26,7 @@ Supported nose Idioms
|
|||
* setup and teardown at module/class/method level
|
||||
* SkipTest exceptions and markers
|
||||
* setup/teardown decorators
|
||||
* ``yield``-based tests and their setup
|
||||
* ``yield``-based tests and their setup (considered deprecated as of pytest 3.0)
|
||||
* ``__test__`` attribute on modules/classes/functions
|
||||
* general usage of nose utilities
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
.. _pythonpath:
|
||||
|
||||
pytest import mechanisms and ``sys.path``/``PYTHONPATH``
|
||||
========================================================
|
||||
|
||||
Here's a list of scenarios where pytest may need to change ``sys.path`` in order
|
||||
to import test modules or ``conftest.py`` files.
|
||||
|
||||
Test modules / ``conftest.py`` files inside packages
|
||||
----------------------------------------------------
|
||||
|
||||
Consider this file and directory layout::
|
||||
|
||||
root/
|
||||
|- foo/
|
||||
|- __init__.py
|
||||
|- conftest.py
|
||||
|- bar/
|
||||
|- __init__.py
|
||||
|- tests/
|
||||
|- __init__.py
|
||||
|- test_foo.py
|
||||
|
||||
|
||||
When executing::
|
||||
|
||||
pytest root/
|
||||
|
||||
|
||||
|
||||
pytest will find ``foo/bar/tests/test_foo.py`` and realize it is part of a package given that
|
||||
there's an ``__init__.py`` file in the same folder. It will then search upwards until it can find the
|
||||
last folder which still contains an ``__init__.py`` file in order to find the package *root* (in
|
||||
this case ``foo/``). To load the module, it will insert ``root/`` to the front of
|
||||
``sys.path`` (if not there already) in order to load
|
||||
``test_foo.py`` as the *module* ``foo.bar.tests.test_foo``.
|
||||
|
||||
The same logic applies to the ``conftest.py`` file: it will be imported as ``foo.conftest`` module.
|
||||
|
||||
Preserving the full package name is important when tests live in a package to avoid problems
|
||||
and allow test modules to have duplicated names. This is also discussed in details in
|
||||
:ref:`test discovery`.
|
||||
|
||||
Standalone test modules / ``conftest.py`` files
|
||||
-----------------------------------------------
|
||||
|
||||
Consider this file and directory layout::
|
||||
|
||||
root/
|
||||
|- foo/
|
||||
|- conftest.py
|
||||
|- bar/
|
||||
|- tests/
|
||||
|- test_foo.py
|
||||
|
||||
|
||||
When executing::
|
||||
|
||||
pytest root/
|
||||
|
||||
pytest will find ``foo/bar/tests/test_foo.py`` and realize it is NOT part of a package given that
|
||||
there's no ``__init__.py`` file in the same folder. It will then add ``root/foo/bar/tests`` to
|
||||
``sys.path`` in order to import ``test_foo.py`` as the *module* ``test_foo``. The same is done
|
||||
with the ``conftest.py`` file by adding ``root/foo`` to ``sys.path`` to import it as ``conftest``.
|
||||
|
||||
For this reason this layout cannot have test modules with the same name, as they all will be
|
||||
imported in the global import namespace.
|
||||
|
||||
This is also discussed in details in :ref:`test discovery`.
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ You can invoke testing through the Python interpreter from the command line::
|
|||
python -m pytest [...]
|
||||
|
||||
This is almost equivalent to invoking the command line script ``pytest [...]``
|
||||
directly, except that python will also add the current directory to ``sys.path``.
|
||||
directly, except that Python will also add the current directory to ``sys.path``.
|
||||
|
||||
Possible exit codes
|
||||
--------------------------------------------------------------
|
||||
|
|
|
@ -49,7 +49,7 @@ Plugin discovery order at tool startup
|
|||
|
||||
Note that pytest does not find ``conftest.py`` files in deeper nested
|
||||
sub directories at tool startup. It is usually a good idea to keep
|
||||
your conftest.py file in the top level test or project root directory.
|
||||
your ``conftest.py`` file in the top level test or project root directory.
|
||||
|
||||
* by recursively loading all plugins specified by the
|
||||
``pytest_plugins`` variable in ``conftest.py`` files
|
||||
|
@ -94,10 +94,12 @@ Here is how you might run it::
|
|||
If you have ``conftest.py`` files which do not reside in a
|
||||
python package directory (i.e. one containing an ``__init__.py``) then
|
||||
"import conftest" can be ambiguous because there might be other
|
||||
``conftest.py`` files as well on your PYTHONPATH or ``sys.path``.
|
||||
``conftest.py`` files as well on your ``PYTHONPATH`` or ``sys.path``.
|
||||
It is thus good practice for projects to either put ``conftest.py``
|
||||
under a package scope or to never import anything from a
|
||||
conftest.py file.
|
||||
``conftest.py`` file.
|
||||
|
||||
See also: :ref:`pythonpath`.
|
||||
|
||||
|
||||
Writing your own plugin
|
||||
|
|
Loading…
Reference in New Issue