Testing API

Added in version 1.6.

Sphinx provides utility functions and pytest fixtures to make it easier to write test suites that build multiple Sphinx documentation projects.

Using pytest plugin

To use pytest helpers that are provided by sphinx.testing, add the 'sphinx.testing.fixtures' plugin to your conftest.py file as follows:

pytest_plugins = ['sphinx.testing.fixtures']

Markers

@pytest.mark.test_params(...)

Parameters associated with a test.

Parameters:

shared_result (str) – A key that allows sharing the build result, status, and warning between tests that use the same key.

When multiple tests with a module are marked with the same shared_result value, they will share the same build result as well as status and warning buffers. This allows related tests to avoid redundant rebuilds and reuse the same build context.

@pytest.mark.test_params(shared_result="html_build")
def test_html_title(app: SphinxTestApp) -> None:
    app.build()
    # ... test something about the HTML output ...

@pytest.mark.test_params(shared_result="html_build")
def test_html_index(app: SphinxTestApp) -> None:
    app.build()
    # ... test something else about the HTML output ...
@pytest.mark.sphinx(buildername="html", *, testroot="root", ...)

Arguments to initialize the Sphinx test application.

Parameters:
  • buildername (str) – Builder to use.

  • testroot (str) – Test root directory to use.

  • srcdir – Source directory (overridden when shared_result is used).

  • confoverrides (dict) – Configuration values to override.

  • freshenv (bool) – Whether to refresh the environment.

  • warningiserror (bool) – Treat warnings as errors.

  • tags – List of tags to set.

  • verbosity (int) – Verbosity level.

  • parallel (int) – Number of parallel processes.

  • builddir – Build directory.

  • docutils_conf – Docutils configuration.

@pytest.mark.sphinx("html", testroot="something")
def test_html_output(app: SphinxTestApp) -> None:
    app.build()
    # ... test something about the HTML output ...

Fixtures

sphinx.testing.fixtures.rootdir()
Scope:

session

Defaults to None so tests operate on (empty) temporary paths.

Can be overridden in a project’s conftest.py to return a Path to a directory, containing multiple Sphinx documentation sources under sub-directories prefixed with test-.

@pytest.fixture(scope='session')
def rootdir() -> pathlib.Path | None:
    return pathlib.Path(__file__).parent / 'docsets'
tests/
├── conftest.py  <-- defines rootdir fixture
├── docsets/
├── test-example1/
│   ├── conf.py
│   └── index.rst
├── test-example2/
│   ├── conf.py
│   └── index.rst
└── test_something.py
sphinx.testing.fixtures.sphinx_test_tempdir()
Scope:

session

Base temporary directory Path used for building the test apps.

sphinx.testing.fixtures.app_params()

The positional args and keyword kwargs used to build the SphinxTestApp for this test. These are derived from the pytest.mark.sphinx(), pytest.mark.test_params(), and default settings.

If rootdir fixture is not None, the contents of rootdir / f'test-{testroot}' get copied into the source directory that the app would build in.

Returns a namedtuple of (args, kwargs).

sphinx.testing.fixtures.make_app()

Factory function that constructs a SphinxTestApp from app_params.

def test_something(make_app: Callable[..., SphinxTestApp]) -> None:
    app = make_app("html")
    app.build()
    # ... test something about the built documentation ...
sphinx.testing.fixtures.app()

A SphinxTestApp constructed from app_params.

def test_something(app: SphinxTestApp) -> None:
    app.build()
    # ... test something about the built documentation ...
sphinx.testing.fixtures.if_graphviz_found()

Skip the test if graphviz_dot is not configured or the binary is unavailable.

@pytest.mark.usefixtures('if_graphviz_found')
def test_graphviz_diagram(app: SphinxTestApp) -> None:
    app.build()
    # ... test something about the graphviz diagram ...
sphinx.testing.fixtures.rollback_sysmodules()

Iterator that snapshots sys.modules before the test and removes any modules imported during the test body. Helps tests reload target modules to clear caches.

This mostly exists to help test sphinx.ext.autodoc.

@pytest.mark.usefixtures('rollback_sysmodules')
def test_module_reload(app: SphinxTestApp) -> None:
    import my_extension
    # ... test something about my_extension ...
sphinx.testing.fixtures.status()

Compatibility fixture returning app.status (StringIO).

sphinx.testing.fixtures.warning()

Compatibility fixture returning app.warning (StringIO).

Utilities

class sphinx.testing.util.SphinxTestApp(buildername: str = 'html', srcdir: Path | None = None, builddir: Path | None = None, freshenv: bool = False, confoverrides: dict[str, Any] | None = None, status: StringIO | None = None, warning: StringIO | None = None, tags: Sequence[str] = (), docutils_conf: str | None = None, parallel: int = 0, verbosity: int = 0, warningiserror: bool = False, pdb: bool = False, exception_on_warning: bool = False, **extras: Any)[source]

Bases: Sphinx

A subclass of Sphinx for tests.

The constructor uses some better default values for the initialization parameters and supports arbitrary keywords stored in the extras read-only mapping.

It is recommended to use:

@pytest.mark.sphinx('html', testroot='root')
def test(app):
    app = ...

instead of:

def test():
    app = SphinxTestApp('html', srcdir=srcdir)

In the former case, the ‘app’ fixture takes care of setting the source directory, whereas in the latter, the user must provide it themselves.

extras

A dictionary to store arbitrary data associated with this app.

property status: StringIO

The in-memory text I/O for the application status messages.

property warning: StringIO

The in-memory text I/O for the application warning messages.

class sphinx.testing.util.SphinxTestAppWrapperForSkipBuilding(buildername: str = 'html', srcdir: Path | None = None, builddir: Path | None = None, freshenv: bool = False, confoverrides: dict[str, Any] | None = None, status: StringIO | None = None, warning: StringIO | None = None, tags: Sequence[str] = (), docutils_conf: str | None = None, parallel: int = 0, verbosity: int = 0, warningiserror: bool = False, pdb: bool = False, exception_on_warning: bool = False, **extras: Any)[source]

Bases: SphinxTestApp

A wrapper for SphinxTestApp.

This class is used to speed up the test by skipping app.build() if it has already been built and there are any output files.

Usage

If you want to know more detailed usage, please refer to tests/conftest.py and other test_*.py files under the tests/ directory of the Sphinx source code.