Skip to content

✨ Add public sphinx_design.testing helpers#277

Merged
chrisjsewell merged 1 commit into
mainfrom
brief/22-testing-module
Jul 12, 2026
Merged

✨ Add public sphinx_design.testing helpers#277
chrisjsewell merged 1 commit into
mainfrom
brief/22-testing-module

Conversation

@chrisjsewell

@chrisjsewell chrisjsewell commented Jul 12, 2026

Copy link
Copy Markdown
Member

Ships the test suite's doctree-XML normalization as a semi-public module, so downstream extensions (e.g. sphinx-design-elements) can stop re-implementing it.

Changes

  • New sphinx_design.testing module: normalize_doctree_xml(text, extra_attributes=()) (papers over docutils 0.22's boolean-attribute serialization change; no-op on older docutils) and the SphinxBuilder wrapper used by our own fixtures. Module docstring states the support policy: signatures covered by deprecation policy, exact output not guaranteed stable across docutils versions.
  • Importable with only sphinx_design installed: no pytest import, and sphinx.testing is imported only for type checking (verified empirically in a bare venv on sphinx 7.3.7, where sphinx.testing.util would otherwise require defusedxml).
  • Works on the full supported range: SphinxTestApp's public status/warning properties only exist from sphinx 7.3, so SphinxBuilder falls back to the private streams on the 7.2 floor.
  • tests/conftest.py shrinks to thin wrappers re-exporting the public helpers; existing test signatures unchanged.
  • New docs page ("Testing utilities") under the Development section; unit tests for both docutils serialization code paths.

Verification

  • Full suite green on pinned sphinx 7.2.6 (139 passed, version verified in-venv), and on the standard matrix (sphinx 9.0.4 / docutils 0.22, which exercises the normalization path)
  • Bare-import check on sphinx 7.3.7 with no test extras installed: import sphinx_design.testing succeeds
  • py.typed ships in the wheel, module fully annotated, both mypy configurations clean

Closes #260

Lift the test-suite's doctree-XML normalizer into a new semi-public
`sphinx_design.testing` module so downstream extensions can reuse it for
their doctree regression tests instead of re-implementing it. The
`normalize_doctree_xml` helper and the `SphinxBuilder` wrapper are now
importable with only `sphinx_design` installed (no pytest/test extras);
the pytest fixtures in conftest become thin re-exporting wrappers.
@chrisjsewell chrisjsewell force-pushed the brief/22-testing-module branch from 6268fca to 2974a20 Compare July 12, 2026 17:46
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.80328% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.40%. Comparing base (1bfd79d) to head (2974a20).

Files with missing lines Patch % Lines
sphinx_design/testing.py 91.80% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #277      +/-   ##
==========================================
+ Coverage   90.33%   90.40%   +0.07%     
==========================================
  Files          12       13       +1     
  Lines        1086     1147      +61     
==========================================
+ Hits          981     1037      +56     
- Misses        105      110       +5     
Flag Coverage Δ
pytests 90.40% <91.80%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@chrisjsewell chrisjsewell left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Add public sphinx_design.testing helpers

Overview

Promotes the test suite's doctree-XML normalization (normalize_doctree_xml) and the SphinxBuilder wrapper from tests/conftest.py into a shipped, semi-public sphinx_design.testing module, so downstream extensions can reuse them instead of re-implementing. conftest.py shrinks to thin re-exports, a docs page and CHANGELOG entry are added, and unit tests cover both docutils serialization code paths. Nicely scoped, well-documented, and clean.

What's done well

  • Import hygiene is correct. sphinx.testing is under TYPE_CHECKING only and pytest isn't imported, so import sphinx_design.testing works with only the package installed — the stated goal. py.typed is already present, and since [tool.flit.sdist] only excludes tests//docs//style/, the new in-package module ships correctly.
  • Version-floor handling. The status/warnings getattr(..., None) fallback to _status/_warning correctly papers over SphinxTestApp.status/warning being properties only from sphinx 7.3; the singular warning attr vs. plural warnings property is matched right.
  • Global-lookup trick is deliberate and correct. normalize_doctree_xml reads the module global _DOCUTILS_0_22_PLUS at call time, which is what lets the unit tests monkeypatch both branches regardless of installed docutils. Good.
  • Regex safety. re.escape on extra_attributes, the leading-space + ="1"/="0" anchors, and the known-attribute allowlist keep the substitution tight; the ordered-alternation translatable/translated overlap is safe because of the ="…" anchor. The textual-heuristic caveat (text content mimicking attr="1") is honestly documented.
  • No stale references. DOCUTILS_0_22_PLUS and the now-unused re/nodes/SphinxTestApp/docutils_version_info imports are removed from conftest, and nothing else in tests/ referenced them; from .conftest import SphinxBuilder (test_snippets.py) still resolves via the re-export.

Minor notes (non-blocking)

  • Fallback branch is only covered on the 7.2 floor CI job. The _status/_warning private-stream path in status/warnings never executes on the main matrix (7.3+ takes the property path), and there's no unit test for SphinxBuilder. That's the most fragile part of the diff, yet it's the least exercised. Consider a tiny test with a stub object exposing only _status/_warning to lock the fallback, so a regression wouldn't hide until the pinned-floor job runs.
  • get_doctree relative_to can raise ValueError if a node's source isn't under src_path. This is moved verbatim (not introduced here), so no action needed — just flagging that the behavior now lives in a public API where a downstream caller with an unexpected source path would hit it.
  • Doc example references file_regression without noting it comes from pytest-regressions; a one-line mention would help downstream readers copy-pasting it.
  • Micro: normalize_doctree_xml rebuilds/compiles two regexes per call. Irrelevant for test-time usage — not worth changing.

Correctness / risk

No correctness issues found. The refactor is behavior-preserving for existing tests (signatures unchanged, fixture still callable as normalize_doctree_xml(text)), the new module has no import-time side effects beyond a version check, and CI (pre-commit + RTD) is green.

Verdict: Looks good to merge. 👍


Generated by Claude Code

@chrisjsewell chrisjsewell merged commit 6e06c98 into main Jul 12, 2026
25 checks passed
@chrisjsewell chrisjsewell deleted the brief/22-testing-module branch July 12, 2026 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide normalize_doctree_xml via sphinx_design.testing

1 participant