Skip to content

Commit 0ac3eaa

Browse files
authored
Merge pull request #1735 from flub/reinterpret-docs
Document the re-writing of plugins
2 parents 8a73a2a + 0a53797 commit 0ac3eaa

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

doc/en/writing_plugins.rst

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,63 @@ If a package is installed this way, ``pytest`` will load
176176
to make it easy for users to find your plugin.
177177

178178

179+
Assertion Rewriting
180+
-------------------
181+
182+
One of the main features of ``pytest`` is the use of plain assert
183+
statements and the detailed introspection of expressions upon
184+
assertion failures. This is provided by "assertion rewriting" which
185+
modifies the parsed AST before it gets compiled to bytecode. This is
186+
done via a :pep:`302` import hook which gets installed early on when
187+
``pytest`` starts up and will perform this re-writing when modules get
188+
imported. However since we do not want to test different bytecode
189+
then you will run in production this hook only re-writes test modules
190+
themselves as well as any modules which are part of plugins. Any
191+
other imported module will not be re-written and normal assertion
192+
behaviour will happen.
193+
194+
If you have assertion helpers in other modules where you would need
195+
assertion rewriting to be enabled you need to ask ``pytest``
196+
explicitly to re-write this module before it gets imported.
197+
198+
.. autofunction:: pytest.register_assert_rewrite
199+
200+
This is especially important when you write a pytest plugin which is
201+
created using a package. The import hook only treats ``conftest.py``
202+
files and any modules which are listed in the ``pytest11`` entrypoint
203+
as plugins. As an example consider the following package::
204+
205+
pytest_foo/__init__.py
206+
pytest_foo/plugin.py
207+
pytest_foo/helper.py
208+
209+
With the following typical ``setup.py`` extract:
210+
211+
.. code-block:: python
212+
213+
setup(
214+
...
215+
entry_points={'pytest11': ['foo = pytest_foo.plugin']},
216+
...
217+
)
218+
219+
In this case only ``pytest_foo/plugin.py`` will be re-written. If the
220+
helper module also contains assert statements which need to be
221+
re-written it needs to be marked as such, before it gets imported.
222+
This is easiest by marking it for re-writing inside the
223+
``__init__.py`` module, which will always be imported first when a
224+
module inside a package is imported. This way ``plugin.py`` can still
225+
import ``helper.py`` normally. The contents of
226+
``pytest_foo/__init__.py`` will then need to look like this:
227+
228+
.. code-block:: python
229+
230+
import pytest
231+
232+
pytest.register_assert_rewrite('pytest_foo.helper')
233+
234+
235+
179236
Requiring/Loading plugins in a test module or conftest file
180237
-----------------------------------------------------------
181238

@@ -190,6 +247,16 @@ will be loaded as well. You can also use dotted path like this::
190247

191248
which will import the specified module as a ``pytest`` plugin.
192249

250+
Plugins imported like this will automatically be marked to require
251+
assertion rewriting using the :func:`pytest.register_assert_rewrite`
252+
mechanism. However for this to have any effect the module must not be
253+
imported already, it it was already imported at the time the
254+
``pytest_plugins`` statement is processed a warning will result and
255+
assertions inside the plugin will not be re-written. To fix this you
256+
can either call :func:`pytest.register_assert_rewrite` yourself before
257+
the module is imported, or you can arrange the code to delay the
258+
importing until after the plugin is registered.
259+
193260

194261
Accessing another plugin by name
195262
--------------------------------

0 commit comments

Comments
 (0)