Skip to content

Skip fixture-discovery scan for fixture-less plugins - #15086

Closed
Dextheking1 wants to merge 3 commits into
pytest-dev:mainfrom
Dextheking1:perf/skip-fixture-introspection-14877
Closed

Dextheking1 wants to merge 3 commits into
pytest-dev:mainfrom
Dextheking1:perf/skip-fixture-introspection-14877

Conversation

@Dextheking1

Copy link
Copy Markdown

Problem

FixtureManager.parsefactories() walks dir(plugin) and validates every
attribute of every registered plugin on every Config build, even though
most builtin plugins define zero fixtures. Per the profiling in #14877 this
is pure overhead, paid repeatedly by anything that builds many configs
(pytester-based suites first of all — i.e. pytest's own test suite).

Approach

Holders can now declare that they define no fixtures with the
__pytest_no_fixtures__ marker; parsefactories returns early for them
(the lookup uses safe_getattr, so arbitrary user objects are unaffected).

The marker is applied to:

  • all 20 fixture-less builtin plugin modules (mark, main, runner,
    helpconfig, python, terminal, debugging, unittest, skipping,
    legacypath, pastebin, assertion, setuponly, setupplan,
    stepwise, unraisableexception, threadexception, warnings,
    reports, faulthandler)
  • TerminalReporter (registered as an instance)
  • the Config and PytestPluginManager objects

22 holders skipped per session build in total. Modules that do define
fixtures (fixtures — including the pytestconfig fixture, capture,
tmpdir, monkeypatch, recwarn, junitxml, doctest, cacheprovider,
logging, subtests) are untouched and scanned exactly as before.

To address the failure mode noted in the issue (a fixture added to a marked
holder would be silently dropped),
testing/test_meta.py::test_no_fixtures_opt_out_holders_define_no_fixtures
walks every marked holder and fails if any of them actually defines a
fixture.

Measured

Per session build + collect-only run (default plugin set):

before after
attribute introspections (dir() names scanned) 2258 1052 (−53%)
_check_for_wrapped_fixture validations 2079 937 (−55%)
holders skipped via opt-out 0 22
fixtures registered 20 20 (identical)

testing/test_config.py (-n 8, pytester-heavy, single runs each):
31.67s → 29.80s. --fixtures output verified identical (modulo shifted
line numbers from the added marker lines).

Tests

  • new guard test test_no_fixtures_opt_out_holders_define_no_fixtures: passes
  • testing/test_meta.py, testing/test_pluginmanager.py: 108 passed, 1 skipped
  • testing/python/fixtures.py: 242 passed, 3 xfailed
  • testing/test_config.py: 290 passed, 1 xfailed
  • testing/test_doctest.py, testing/test_conftest.py: 202 passed, 1 skipped, 1 xfailed

Changelog entry added (changelog/14877.improvement.rst).

Note on the design

The issue leans toward push-based discovery or per-holder caching over a
manual flag. This PR takes the flag direction because it is the minimal,
reviewable change that captures the measured win with zero behavior change
for fixture-defining plugins, and the new meta test removes the flag's
silent-drop failure mode. Happy to rework toward caching if maintainers
prefer.

Closes #14877.

FixtureManager.parsefactories() walked dir() and validated every attribute
of every registered plugin on each Config build, even though most builtin
plugins define no fixtures. Holders can now declare this with the
__pytest_no_fixtures__ marker, in which case the scan is skipped entirely.

The marker is applied to all fixture-less builtin plugin modules, the
TerminalReporter, and the Config / PytestPluginManager objects (22 holders
per session build). Attribute introspections per session build drop from
2258 to 1052 (-53%) with an identical registered fixture set.

A meta test guards the marker: it fails if any marked holder actually
defines a fixture, so a fixture can never be silently dropped.

Closes pytest-dev#14877.
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fixture discovery scans every attribute of every registered plugin, on every Config

2 participants