diff --git a/doc/en/goodpractices.rst b/doc/en/goodpractices.rst index 5f6ea710b..ff71f1c9c 100644 --- a/doc/en/goodpractices.rst +++ b/doc/en/goodpractices.rst @@ -56,7 +56,44 @@ of ``mypkg``. Note that using this scheme your test files must have **unique names**, because ``pytest`` will import them as *top-level* modules since there are no packages -to derive a full package name from. +to derive a full package name from. In other words, the test files in the example above will +be imported as ``test_app`` and ``test_view`` top-level modules by adding ``tests/`` to +``sys.path``. + +If you need to have test modules with the same name, you might add ``__init__.py`` files to your +``tests`` folder and subfolders, changing them to packages:: + + mypkg/ + ... + tests/ + __init__.py + foo/ + __init__.py + test_view.py + bar/ + __init__.py + test_view.py + +Now pytest will load the modules as ``tests.foo.test_view`` and ``tests.bar.test_view``, allowing +you to have modules with the same name. But now this introduces a subtle problem: in order to load +the test modules from the ``tests`` directory, pytest prepends the root of the repository to +``sys.path``, which adds the side-effect that now ``mypkg`` is also importable. +This is problematic if you are using a tool like `tox`_ to test your package in a virtual environment, +because you want to test the *installed* version of your package, not the local code from the repository. + +There are a couple of solutions to this: + +* Do not add the ``tests/__init__.py`` file. This will cause your test modules to be loaded as + ``foo.test_view`` and ``bar.test_view``, which is usually fine and avoids having the root of + the repository being added to the ``PYTHONPATH``. + +* Add ``addopts=--import-mode=append`` to your ``pytest.ini`` file. This will cause ``pytest`` to + load your modules by *appending* the root directory instead of prepending. + +* Alternatively, consider using the ``src`` layout explained in detail in this excellent + `blog post by Ionel Cristian Mărieș `_ + which prevents a lot of the pitfalls described here. + Tests as part of application code ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^