From 98f3a429a444fae87ac49369a1273c85a72c0270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 23 Dec 2024 13:46:17 +0100 Subject: [PATCH] tests: Refactor fixtures and helpers --- tests/conftest.py | 114 +++++++++++++++++++++++++++++-------------- tests/helpers.py | 94 +++++++++++++++++++++++++++++++++++ tests/test_themes.py | 10 ++-- 3 files changed, 174 insertions(+), 44 deletions(-) create mode 100644 tests/helpers.py diff --git a/tests/conftest.py b/tests/conftest.py index 88105e4c..1c53cba4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,25 +2,29 @@ from __future__ import annotations -from collections import ChainMap -from typing import TYPE_CHECKING, Any +from collections.abc import Iterator +from typing import TYPE_CHECKING import pytest -from markdown.core import Markdown -from mkdocs.config.defaults import MkDocsConfig + +from tests import helpers if TYPE_CHECKING: from collections.abc import Iterator from pathlib import Path - from mkdocs import config + from markdown.core import Markdown + from mkdocs.config.defaults import MkDocsConfig from mkdocstrings.plugin import MkdocstringsPlugin from mkdocstrings_handlers.python.handler import PythonHandler +# -------------------------------------------- +# Function-scoped fixtures. +# -------------------------------------------- @pytest.fixture(name="mkdocs_conf") -def fixture_mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Iterator[config.Config]: +def fixture_mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Iterator[MkDocsConfig]: """Yield a MkDocs configuration object. Parameters: @@ -30,34 +34,12 @@ def fixture_mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Itera Yields: MkDocs config. """ - conf = MkDocsConfig() - while hasattr(request, "_parent_request") and hasattr(request._parent_request, "_parent_request"): - request = request._parent_request - - conf_dict = { - "site_name": "foo", - "site_url": "https://example.org/", - "site_dir": str(tmp_path), - "plugins": [{"mkdocstrings": {"default_handler": "python"}}], - **getattr(request, "param", {}), - } - # Re-create it manually as a workaround for https://github.com/mkdocs/mkdocs/issues/2289 - mdx_configs: dict[str, Any] = dict(ChainMap(*conf_dict.get("markdown_extensions", []))) - - conf.load_dict(conf_dict) - assert conf.validate() == ([], []) - - conf["mdx_configs"] = mdx_configs - conf["markdown_extensions"].insert(0, "toc") # Guaranteed to be added by MkDocs. - - conf = conf["plugins"]["mkdocstrings"].on_config(conf) - conf = conf["plugins"]["autorefs"].on_config(conf) - yield conf - conf["plugins"]["mkdocstrings"].on_post_build(conf) + with helpers.mkdocs_conf(request, tmp_path) as mkdocs_conf: + yield mkdocs_conf @pytest.fixture(name="plugin") -def fixture_plugin(mkdocs_conf: config.Config) -> MkdocstringsPlugin: +def fixture_plugin(mkdocs_conf: MkDocsConfig) -> MkdocstringsPlugin: """Return a plugin instance. Parameters: @@ -66,11 +48,11 @@ def fixture_plugin(mkdocs_conf: config.Config) -> MkdocstringsPlugin: Returns: mkdocstrings plugin instance. """ - return mkdocs_conf["plugins"]["mkdocstrings"] + return helpers.plugin(mkdocs_conf) @pytest.fixture(name="ext_markdown") -def fixture_ext_markdown(mkdocs_conf: config.Config) -> Markdown: +def fixture_ext_markdown(mkdocs_conf: MkDocsConfig) -> Markdown: """Return a Markdown instance with MkdocstringsExtension. Parameters: @@ -79,7 +61,7 @@ def fixture_ext_markdown(mkdocs_conf: config.Config) -> Markdown: Returns: A Markdown instance. """ - return Markdown(extensions=mkdocs_conf["markdown_extensions"], extension_configs=mkdocs_conf["mdx_configs"]) + return helpers.ext_markdown(mkdocs_conf) @pytest.fixture(name="handler") @@ -92,6 +74,64 @@ def fixture_handler(plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> Pytho Returns: A handler instance. """ - handler = plugin.handlers.get_handler("python") - handler._update_env(ext_markdown, plugin.handlers._config) - return handler # type: ignore[return-value] + return helpers.handler(plugin, ext_markdown) + + +# -------------------------------------------- +# Session-scoped fixtures. +# -------------------------------------------- +@pytest.fixture(name="session_mkdocs_conf", scope="session") +def fixture_session_mkdocs_conf( + request: pytest.FixtureRequest, + tmp_path_factory: pytest.TempPathFactory, +) -> Iterator[MkDocsConfig]: + """Yield a MkDocs configuration object. + + Parameters: + request: Pytest fixture. + tmp_path: Pytest fixture. + + Yields: + MkDocs config. + """ + with helpers.mkdocs_conf(request, tmp_path_factory.mktemp("project")) as mkdocs_conf: + yield mkdocs_conf + + +@pytest.fixture(name="session_plugin", scope="session") +def fixture_session_plugin(session_mkdocs_conf: MkDocsConfig) -> MkdocstringsPlugin: + """Return a plugin instance. + + Parameters: + mkdocs_conf: Pytest fixture (see conftest.py). + + Returns: + mkdocstrings plugin instance. + """ + return helpers.plugin(session_mkdocs_conf) + + +@pytest.fixture(name="session_ext_markdown", scope="session") +def fixture_session_ext_markdown(session_mkdocs_conf: MkDocsConfig) -> Markdown: + """Return a Markdown instance with MkdocstringsExtension. + + Parameters: + mkdocs_conf: Pytest fixture (see conftest.py). + + Returns: + A Markdown instance. + """ + return helpers.ext_markdown(session_mkdocs_conf) + + +@pytest.fixture(name="session_handler", scope="session") +def fixture_session_handler(session_plugin: MkdocstringsPlugin, session_ext_markdown: Markdown) -> PythonHandler: + """Return a handler instance. + + Parameters: + plugin: Pytest fixture (see conftest.py). + + Returns: + A handler instance. + """ + return helpers.handler(session_plugin, session_ext_markdown) diff --git a/tests/helpers.py b/tests/helpers.py new file mode 100644 index 00000000..91ea4eee --- /dev/null +++ b/tests/helpers.py @@ -0,0 +1,94 @@ +"""Configuration for the pytest test suite.""" + +from __future__ import annotations + +from collections import ChainMap +from contextlib import contextmanager +from typing import TYPE_CHECKING, Any + +from markdown.core import Markdown +from mkdocs.config.defaults import MkDocsConfig + +if TYPE_CHECKING: + from collections.abc import Iterator + from pathlib import Path + + import pytest + from mkdocstrings.plugin import MkdocstringsPlugin + + from mkdocstrings_handlers.python.handler import PythonHandler + + +@contextmanager +def mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Iterator[MkDocsConfig]: + """Yield a MkDocs configuration object. + + Parameters: + request: Pytest request fixture. + tmp_path: Temporary path. + + Yields: + MkDocs config. + """ + conf = MkDocsConfig() + while hasattr(request, "_parent_request") and hasattr(request._parent_request, "_parent_request"): + request = request._parent_request + + conf_dict = { + "site_name": "foo", + "site_url": "https://example.org/", + "site_dir": str(tmp_path), + "plugins": [{"mkdocstrings": {"default_handler": "python"}}], + **getattr(request, "param", {}), + } + # Re-create it manually as a workaround for https://github.com/mkdocs/mkdocs/issues/2289 + mdx_configs: dict[str, Any] = dict(ChainMap(*conf_dict.get("markdown_extensions", []))) + + conf.load_dict(conf_dict) + assert conf.validate() == ([], []) + + conf["mdx_configs"] = mdx_configs + conf["markdown_extensions"].insert(0, "toc") # Guaranteed to be added by MkDocs. + + conf = conf["plugins"]["mkdocstrings"].on_config(conf) + conf = conf["plugins"]["autorefs"].on_config(conf) + yield conf + conf["plugins"]["mkdocstrings"].on_post_build(conf) + + +def plugin(mkdocs_conf: MkDocsConfig) -> MkdocstringsPlugin: + """Return a plugin instance. + + Parameters: + mkdocs_conf: MkDocs configuration. + + Returns: + mkdocstrings plugin instance. + """ + return mkdocs_conf["plugins"]["mkdocstrings"] + + +def ext_markdown(mkdocs_conf: MkDocsConfig) -> Markdown: + """Return a Markdown instance with MkdocstringsExtension. + + Parameters: + mkdocs_conf: MkDocs configuration. + + Returns: + A Markdown instance. + """ + return Markdown(extensions=mkdocs_conf["markdown_extensions"], extension_configs=mkdocs_conf["mdx_configs"]) + + +def handler(plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> PythonHandler: + """Return a handler instance. + + Parameters: + plugin: Plugin instance. + + Returns: + A handler instance. + """ + handler = plugin.handlers.get_handler("python") + handler._update_env(ext_markdown, plugin.handlers._config) + return handler # type: ignore[return-value] diff --git a/tests/test_themes.py b/tests/test_themes.py index a4ad0d59..035f453e 100644 --- a/tests/test_themes.py +++ b/tests/test_themes.py @@ -7,8 +7,7 @@ import pytest if TYPE_CHECKING: - from markdown import Markdown - from mkdocstrings.plugin import MkdocstringsPlugin + from mkdocstrings.handlers.python import PythonHandler @pytest.mark.parametrize( @@ -32,15 +31,12 @@ "mkdocstrings_handlers.python", ], ) -def test_render_themes_templates_python(identifier: str, plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> None: +def test_render_themes_templates_python(identifier: str, handler: PythonHandler) -> None: """Test rendering of a given theme's templates. Parameters: identifier: Parametrized identifier. - plugin: Pytest fixture (see conftest.py). - ext_markdown: Pytest fixture (see conftest.py). + handler: Python handler (fixture). """ - handler = plugin.handlers.get_handler("python") - handler._update_env(ext_markdown, plugin.handlers._config) data = handler.collect(identifier, {}) handler.render(data, {})