@@ -30,68 +30,106 @@ Within Python modules, ``pytest`` also discovers tests using the standard
3030
3131
3232Choosing a test layout / import rules
33- ------------------------------------------
33+ -------------------------------------
3434
3535``pytest `` supports two common test layouts:
3636
37- * putting tests into an extra directory outside your actual application
38- code, useful if you have many functional tests or for other reasons
39- want to keep tests separate from actual application code (often a good
40- idea)::
37+ Tests outside application code
38+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4139
42- setup.py # your setuptools Python package metadata
40+ Putting tests into an extra directory outside your actual application code
41+ might be useful if you have many functional tests or for other reasons want
42+ to keep tests separate from actual application code (often a good idea)::
43+
44+ setup.py
4345 mypkg/
4446 __init__.py
45- appmodule.py
47+ app.py
48+ view.py
4649 tests/
4750 test_app.py
51+ test_view.py
4852 ...
4953
54+ This way your tests can run easily against an installed version
55+ of ``mypkg ``.
56+
57+ Note that using this scheme your test files must have **unique names **, because
58+ ``pytest `` will import them as *top-level * modules since there are no packages
59+ to derive a full package name from. In other words, the test files in the example above will
60+ be imported as ``test_app `` and ``test_view `` top-level modules by adding ``tests/ `` to
61+ ``sys.path ``.
5062
51- * inlining test directories into your application package, useful if you
52- have direct relation between (unit-)test and application modules and
53- want to distribute your tests along with your application::
63+ If you need to have test modules with the same name, you might add ``__init__.py `` files to your
64+ ``tests `` folder and subfolders, changing them to packages::
5465
55- setup.py # your setuptools Python package metadata
66+ setup.py
5667 mypkg/
57- __init__.py
58- appmodule.py
5968 ...
60- test/
61- test_app.py
62- ...
69+ tests/
70+ __init__.py
71+ foo/
72+ __init__.py
73+ test_view.py
74+ bar/
75+ __init__.py
76+ test_view.py
77+
78+ Now pytest will load the modules as ``tests.foo.test_view `` and ``tests.bar.test_view ``, allowing
79+ you to have modules with the same name. But now this introduces a subtle problem: in order to load
80+ the test modules from the ``tests `` directory, pytest prepends the root of the repository to
81+ ``sys.path ``, which adds the side-effect that now ``mypkg `` is also importable.
82+ This is problematic if you are using a tool like `tox `_ to test your package in a virtual environment,
83+ because you want to test the *installed * version of your package, not the local code from the repository.
84+
85+ In this situation, it is **strongly ** suggested to use a ``src `` layout where application root package resides in a
86+ sub-directory of your root::
87+
88+ setup.py
89+ src/
90+ mypkg/
91+ __init__.py
92+ app.py
93+ view.py
94+ tests/
95+ __init__.py
96+ foo/
97+ __init__.py
98+ test_view.py
99+ bar/
100+ __init__.py
101+ test_view.py
63102
64- Important notes relating to both schemes:
65103
66- - **make sure that "mypkg" is importable **, for example by typing once::
104+ This layout prevents a lot of common pitfalls and has many benefits, which are better explained in this excellent
105+ `blog post by Ionel Cristian Mărieș <https://blog.ionelmc.ro/2014/05/25/python-packaging/#the-structure >`_.
67106
68- pip install -e . # install package using setup.py in editable mode
107+ Tests as part of application code
108+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
69109
70- - **avoid "__init__.py" files in your test directories **.
71- This way your tests can run easily against an installed version
72- of ``mypkg ``, independently from the installed package if it contains
73- the tests or not.
110+ Inlining test directories into your application package
111+ is useful if you have direct relation between tests and application modules and
112+ want to distribute them along with your application::
74113
75- - With inlined tests you might put ``__init__.py `` into test
76- directories and make them installable as part of your application.
77- Using the ``pytest --pyargs mypkg `` invocation pytest will
78- discover where mypkg is installed and collect tests from there.
79- With the "external" test you can still distribute tests but they
80- will not be installed or become importable.
114+ setup.py
115+ mypkg/
116+ __init__.py
117+ app.py
118+ view.py
119+ test/
120+ __init__.py
121+ test_app.py
122+ test_view.py
123+ ...
124+
125+ In this scheme, it is easy to your run tests using the ``--pyargs `` option::
81126
82- Typically you can run tests by pointing to test directories or modules::
127+ pytest --pyargs mypkg
83128
84- pytest tests/test_app.py # for external test dirs
85- pytest mypkg/test/test_app.py # for inlined test dirs
86- pytest mypkg # run tests in all below test directories
87- pytest # run all tests below current dir
88- ...
129+ ``pytest `` will discover where ``mypkg `` is installed and collect tests from there.
130+
131+ Note that this layout also works in conjunction with the ``src `` layout mentioned in the previous section.
89132
90- Because of the above ``editable install `` mode you can change your
91- source code (both tests and the app) and rerun tests at will.
92- Once you are done with your work, you can `use tox `_ to make sure
93- that the package is really correct and tests pass in all
94- required configurations.
95133
96134.. note ::
97135
@@ -144,7 +182,13 @@ for installing your application and any dependencies
144182as well as the ``pytest `` package itself. This ensures your code and
145183dependencies are isolated from the system Python installation.
146184
147- If you frequently release code and want to make sure that your actual
185+ You can then install your package in "editable" mode::
186+
187+ pip install -e .
188+
189+ which lets you change your source code (both tests and application) and rerun tests at will.
190+
191+ Once you are done with your work and want to make sure that your actual
148192package passes all tests you may want to look into `tox `_, the
149193virtualenv test automation tool and its `pytest support
150194<https://tox.readthedocs.io/en/latest/example/pytest.html> `_.
@@ -154,11 +198,6 @@ options. It will run tests against the installed package and not
154198against your source code checkout, helping to detect packaging
155199glitches.
156200
157- Continuous integration services such as Jenkins _ can make use of the
158- ``--junitxml=PATH `` option to create a JUnitXML file and generate reports (e.g.
159- by publishing the results in a nice format with the `Jenkins xUnit Plugin
160- <https://wiki.jenkins-ci.org/display/JENKINS/xUnit+Plugin> `_).
161-
162201
163202Integrating with setuptools / ``python setup.py test `` / ``pytest-runner ``
164203--------------------------------------------------------------------------
0 commit comments