Skip to content

Commit 7f46de9

Browse files
committed
Document sphinx.testing
1 parent b062fa9 commit 7f46de9

File tree

1 file changed

+175
-16
lines changed

1 file changed

+175
-16
lines changed

doc/extdev/testing.rst

Lines changed: 175 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,191 @@
11
Testing API
22
===========
33

4-
.. py:module:: sphinx.testing
5-
:synopsis: Utility functions and pytest fixtures for testing.
6-
74
.. versionadded:: 1.6
85

9-
Utility functions and pytest fixtures for testing
10-
are provided in :py:mod:`!sphinx.testing`.
11-
If you are a developer of Sphinx extensions,
12-
you can write unit tests with pytest_.
13-
14-
.. _pytest: https://docs.pytest.org/en/latest/
6+
Sphinx provides utility functions and pytest fixtures to make it easier
7+
to write test suites that build multiple Sphinx documentation projects.
158

16-
``pytest`` configuration
17-
-------------------------
9+
Using ``pytest`` plugin
10+
-----------------------
1811

19-
To use pytest fixtures that are provided by ``sphinx.testing``,
20-
add the ``'sphinx.testing.fixtures'`` plugin
21-
to your test modules or :file:`conftest.py` files as follows:
12+
To use pytest helpers that are provided by ``sphinx.testing``, add the
13+
``'sphinx.testing.fixtures'`` plugin to your :file:`conftest.py` file
14+
as follows:
2215

2316
.. code-block:: python
2417
25-
pytest_plugins = ('sphinx.testing.fixtures',)
18+
pytest_plugins = ['sphinx.testing.fixtures']
19+
20+
Markers
21+
~~~~~~~
22+
23+
.. py:decorator:: pytest.mark.test_params(...)
24+
25+
Parameters associated with a test.
26+
27+
:param str shared_result: A key that allows sharing the build result, status, and warning between tests that use the same key.
28+
29+
When multiple tests with a module are marked with the same
30+
``shared_result`` value, they will share the same build result as
31+
well as status and warning buffers. This allows related tests to
32+
avoid redundant rebuilds and reuse the same build context.
33+
34+
.. code-block:: python
35+
36+
@pytest.mark.test_params(shared_result="html_build")
37+
def test_html_title(app: SphinxTestApp) -> None:
38+
app.build()
39+
# ... test something about the HTML output ...
40+
41+
@pytest.mark.test_params(shared_result="html_build")
42+
def test_html_index(app: SphinxTestApp) -> None:
43+
app.build()
44+
# ... test something else about the HTML output ...
45+
46+
.. py:decorator:: pytest.mark.sphinx(buildername="html", *, testroot="root", ...)
47+
48+
Arguments to initialize the Sphinx test application.
49+
50+
:param str buildername: Builder to use.
51+
:param str testroot: Test root directory to use.
52+
:param srcdir: Source directory (overridden when ``shared_result`` is used).
53+
:param dict confoverrides: Configuration values to override.
54+
:param bool freshenv: Whether to refresh the environment.
55+
:param bool warningiserror: Treat warnings as errors.
56+
:param tags: List of tags to set.
57+
:param int verbosity: Verbosity level.
58+
:param int parallel: Number of parallel processes.
59+
:param builddir: Build directory.
60+
:param docutils_conf: Docutils configuration.
61+
62+
.. code-block:: python
63+
64+
@pytest.mark.sphinx("html", testroot="something")
65+
def test_html_output(app: SphinxTestApp) -> None:
66+
app.build()
67+
# ... test something about the HTML output ...
68+
69+
Fixtures
70+
~~~~~~~~
71+
72+
.. py:function:: sphinx.testing.fixtures.rootdir
73+
74+
:scope: session
75+
76+
Defaults to ``None`` so tests operate on (empty) temporary paths.
77+
78+
Can be overridden in a project's :file:`conftest.py` to return a
79+
:class:`~pathlib.Path` to a directory, containing multiple Sphinx
80+
documentation sources under sub-directories prefixed with `test-`.
81+
82+
.. code-block:: python
83+
84+
@pytest.fixture(scope='session')
85+
def rootdir() -> pathlib.Path | None:
86+
return pathlib.Path(__file__).parent / 'docsets'
87+
88+
.. code-block:: text
89+
90+
tests/
91+
├── conftest.py <-- defines rootdir fixture
92+
├── docsets/
93+
├── test-example1/
94+
│ ├── conf.py
95+
│ └── index.rst
96+
├── test-example2/
97+
│ ├── conf.py
98+
│ └── index.rst
99+
└── test_something.py
100+
101+
.. py:function:: sphinx.testing.fixtures.sphinx_test_tempdir
102+
103+
:scope: session
104+
105+
Base temporary directory :class:`~pathlib.Path` used for building
106+
the test apps.
107+
108+
.. py:function:: sphinx.testing.fixtures.app_params
109+
110+
The positional ``args`` and keyword ``kwargs`` used to build the
111+
:py:class:`~sphinx.testing.util.SphinxTestApp` for this test. These are derived from the
112+
:py:func:`pytest.mark.sphinx`, :py:func:`pytest.mark.test_params`,
113+
and default settings.
114+
115+
If ``rootdir`` fixture is not :py:obj:`None`, the contents of
116+
``rootdir / f'test-{testroot}'`` get copied into the source directory
117+
that the app would build in.
118+
119+
Returns a namedtuple of ``(args, kwargs)``.
120+
121+
.. py:function:: sphinx.testing.fixtures.make_app
122+
123+
Factory function that constructs a :class:`~sphinx.testing.util.SphinxTestApp`
124+
from ``app_params``.
125+
126+
.. code-block:: python
127+
128+
def test_something(make_app: Callable[..., SphinxTestApp]) -> None:
129+
app = make_app("html")
130+
app.build()
131+
# ... test something about the built documentation ...
132+
133+
.. py:function:: sphinx.testing.fixtures.app
134+
135+
A :class:`~sphinx.testing.util.SphinxTestApp` constructed from
136+
``app_params``.
137+
138+
.. code-block:: python
139+
140+
def test_something(app: SphinxTestApp) -> None:
141+
app.build()
142+
# ... test something about the built documentation ...
143+
144+
.. py:function:: sphinx.testing.fixtures.if_graphviz_found
145+
146+
Skip the test if :confval:`graphviz_dot` is not configured or the binary is
147+
unavailable.
148+
149+
.. code-block:: python
150+
151+
@pytest.mark.usefixtures('if_graphviz_found')
152+
def test_graphviz_diagram(app: SphinxTestApp) -> None:
153+
app.build()
154+
# ... test something about the graphviz diagram ...
155+
156+
.. py:function:: sphinx.testing.fixtures.rollback_sysmodules
157+
158+
Iterator that snapshots ``sys.modules`` before the test and removes any
159+
modules imported during the test body. Helps tests reload target modules to
160+
clear caches.
161+
162+
This mostly exists to help test :mod:`sphinx.ext.autodoc`.
163+
164+
.. code-block:: python
165+
166+
@pytest.mark.usefixtures('rollback_sysmodules')
167+
def test_module_reload(app: SphinxTestApp) -> None:
168+
import my_extension
169+
# ... test something about my_extension ...
170+
171+
.. py:function:: sphinx.testing.fixtures.status
172+
173+
Compatibility fixture returning ``app.status`` (``StringIO``).
174+
175+
.. py:function:: sphinx.testing.fixtures.warning
176+
177+
Compatibility fixture returning ``app.warning`` (``StringIO``).
178+
179+
Utilities
180+
---------
181+
182+
.. automodule:: sphinx.testing.util
183+
:members:
184+
:show-inheritance:
26185

27186
Usage
28187
-----
29188

30189
If you want to know more detailed usage,
31190
please refer to :file:`tests/conftest.py` and other :file:`test_*.py` files
32-
under the :file:`tests/` directory.
191+
under the :file:`tests/` directory of the Sphinx source code.

0 commit comments

Comments
 (0)