@@ -30,68 +30,106 @@ Within Python modules, ``pytest`` also discovers tests using the standard
30
30
31
31
32
32
Choosing a test layout / import rules
33
- ------------------------------------------
33
+ -------------------------------------
34
34
35
35
``pytest `` supports two common test layouts:
36
36
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
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41
39
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
43
45
mypkg/
44
46
__init__.py
45
- appmodule.py
47
+ app.py
48
+ view.py
46
49
tests/
47
50
test_app.py
51
+ test_view.py
48
52
...
49
53
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 ``.
50
62
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::
54
65
55
- setup.py # your setuptools Python package metadata
66
+ setup.py
56
67
mypkg/
57
- __init__.py
58
- appmodule.py
59
68
...
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
63
102
64
- Important notes relating to both schemes:
65
103
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 >`_.
67
106
68
- pip install -e . # install package using setup.py in editable mode
107
+ Tests as part of application code
108
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
69
109
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::
74
113
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::
81
126
82
- Typically you can run tests by pointing to test directories or modules::
127
+ pytest --pyargs mypkg
83
128
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.
89
132
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.
95
133
96
134
.. note ::
97
135
@@ -144,7 +182,13 @@ for installing your application and any dependencies
144
182
as well as the ``pytest `` package itself. This ensures your code and
145
183
dependencies are isolated from the system Python installation.
146
184
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
148
192
package passes all tests you may want to look into `tox `_, the
149
193
virtualenv test automation tool and its `pytest support
150
194
<https://tox.readthedocs.io/en/latest/example/pytest.html> `_.
@@ -154,11 +198,6 @@ options. It will run tests against the installed package and not
154
198
against your source code checkout, helping to detect packaging
155
199
glitches.
156
200
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
-
162
201
163
202
Integrating with setuptools / ``python setup.py test `` / ``pytest-runner ``
164
203
--------------------------------------------------------------------------
0 commit comments