Merge pull request #2595 from nicoddemus/docs-rootdir-pythonpath
Clarify PYTHONPATH changes and ``rootdir`` roles
This commit is contained in:
commit
81ad185f0d
|
@ -1079,7 +1079,6 @@ class Config(object):
|
||||||
self.pluginmanager.load_setuptools_entrypoints('pytest11')
|
self.pluginmanager.load_setuptools_entrypoints('pytest11')
|
||||||
self.pluginmanager.consider_env()
|
self.pluginmanager.consider_env()
|
||||||
self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy())
|
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:
|
if self.known_args_namespace.confcutdir is None and self.inifile:
|
||||||
confcutdir = py.path.local(self.inifile).dirname
|
confcutdir = py.path.local(self.inifile).dirname
|
||||||
self.known_args_namespace.confcutdir = confcutdir
|
self.known_args_namespace.confcutdir = confcutdir
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
.. _cache:
|
||||||
|
|
||||||
Cache: working with cross-testrun state
|
Cache: working with cross-testrun state
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,10 @@ Full pytest documentation
|
||||||
plugins
|
plugins
|
||||||
writing_plugins
|
writing_plugins
|
||||||
|
|
||||||
example/index
|
|
||||||
goodpractices
|
goodpractices
|
||||||
|
pythonpath
|
||||||
customize
|
customize
|
||||||
|
example/index
|
||||||
bash-completion
|
bash-completion
|
||||||
|
|
||||||
backwards-compatibility
|
backwards-compatibility
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Basic test configuration
|
Configuration
|
||||||
===================================
|
=============
|
||||||
|
|
||||||
Command line options and configuration file settings
|
Command line options and configuration file settings
|
||||||
-----------------------------------------------------------------
|
-----------------------------------------------------------------
|
||||||
|
@ -15,17 +15,31 @@ which were registered by installed plugins.
|
||||||
.. _rootdir:
|
.. _rootdir:
|
||||||
.. _inifiles:
|
.. _inifiles:
|
||||||
|
|
||||||
initialization: determining rootdir and inifile
|
Initialization: determining rootdir and inifile
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
.. versionadded:: 2.7
|
.. 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 command line arguments (specified test files, paths) and on
|
||||||
the existence of inifiles. The determined rootdir and ini-file are
|
the existence of *ini-files*. The determined ``rootdir`` and *ini-file* are
|
||||||
printed as part of the pytest header. The rootdir is used for constructing
|
printed as part of the pytest header during startup.
|
||||||
"nodeids" during collection and may also be used by plugins to store
|
|
||||||
project/testrun-specific information.
|
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``:
|
Here is the algorithm which finds the rootdir from ``args``:
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
.. _examples:
|
.. _examples:
|
||||||
|
|
||||||
Usages and Examples
|
Examples and customization tricks
|
||||||
===========================================
|
=================================
|
||||||
|
|
||||||
Here is a (growing) list of examples. :ref:`Contact <contact>` us if you
|
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
|
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
|
* setup and teardown at module/class/method level
|
||||||
* SkipTest exceptions and markers
|
* SkipTest exceptions and markers
|
||||||
* setup/teardown decorators
|
* 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
|
* ``__test__`` attribute on modules/classes/functions
|
||||||
* general usage of nose utilities
|
* 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 [...]
|
python -m pytest [...]
|
||||||
|
|
||||||
This is almost equivalent to invoking the command line script ``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
|
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
|
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
|
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
|
* by recursively loading all plugins specified by the
|
||||||
``pytest_plugins`` variable in ``conftest.py`` files
|
``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
|
If you have ``conftest.py`` files which do not reside in a
|
||||||
python package directory (i.e. one containing an ``__init__.py``) then
|
python package directory (i.e. one containing an ``__init__.py``) then
|
||||||
"import conftest" can be ambiguous because there might be other
|
"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``
|
It is thus good practice for projects to either put ``conftest.py``
|
||||||
under a package scope or to never import anything from a
|
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
|
Writing your own plugin
|
||||||
|
|
Loading…
Reference in New Issue