|
1 | 1 | Testing API |
2 | 2 | =========== |
3 | 3 |
|
4 | | -.. py:module:: sphinx.testing |
5 | | - :synopsis: Utility functions and pytest fixtures for testing. |
6 | | - |
7 | 4 | .. versionadded:: 1.6 |
8 | 5 |
|
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. |
15 | 8 |
|
16 | | -``pytest`` configuration |
17 | | -------------------------- |
| 9 | +Using ``pytest`` plugin |
| 10 | +----------------------- |
18 | 11 |
|
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: |
22 | 15 |
|
23 | 16 | .. code-block:: python |
24 | 17 |
|
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: |
26 | 185 |
|
27 | 186 | Usage |
28 | 187 | ----- |
29 | 188 |
|
30 | 189 | If you want to know more detailed usage, |
31 | 190 | 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