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 the 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.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 to use.

  • 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 ...
@pytest.mark.test_params(*, shared_result=...)

Parameters associated with a test.

Parameters:

shared_result (str) – A key that allows sharing the build result, status, and warnings 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.

Attention

shared_result and srcdir are mutually incompatible.

@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 ...

Fixtures

sphinx.testing.fixtures.app: SphinxTestApp
Scope:

function

Provides a SphinxTestApp instance. This is the most common way to get a Sphinx application for testing.

The app can be configured by using the @pytest.mark.sphinx marker.

def test_something(app: SphinxTestApp) -> None:
    app.build()
    # ... test something about the built documentation ...
sphinx.testing.fixtures.make_app(*args: Any, **kwargs: Any) SphinxTestApp
Scope:

function

Factory function that constructs a SphinxTestApp instance for use in tests. This is the preferred way to create instances of the Sphinx object, as it handles clean-up. The arguments are the same as those to SphinxTestApp.

def test_something(make_app: Callable[..., SphinxTestApp]) -> None:
    app = make_app('html')
    app.build()
    # ... test something about the built documentation ...
sphinx.testing.fixtures.app_params: tuple[Sequence[Any], Mapping[str, Any]]
Scope:

function

The positional keyword arguments used to create the SphinxTestApp for this test. These are derived from the markers applied to the test function.

Returns a namedtuple of (args, kwargs).

sphinx.testing.fixtures.rootdir: pathlib.Path | None
Scope:

session

Default is None, meaning tests use empty temporary directories.

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() -> Path:
    return Path(__file__).resolve().parent / 'roots'
tests/
├── conftest.py  <-- defines rootdir fixture
├── roots/
│   ├── test-example1/
│   │   ├── conf.py
│   │   └── index.rst
│   └── test-example2/
│       ├── conf.py
│       └── index.rst
└── test_something.py
sphinx.testing.fixtures.sphinx_test_tempdir: pathlib.Path
Scope:

session

Base temporary directory Path used for building the test apps.

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.

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.

Examples

For practical examples, refer to tests/conftest.py and other test_*.py files under the tests/ directory of the Sphinx source code.