Skip fixture-discovery scan for fixture-less plugins - #15086
Closed
Dextheking1 wants to merge 3 commits into
Closed
Dextheking1 wants to merge 3 commits into
Dextheking1 wants to merge 3 commits into
Conversation
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.
for more information, see https://pre-commit.ci
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
FixtureManager.parsefactories()walksdir(plugin)and validates everyattribute of every registered plugin on every
Configbuild, even thoughmost 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;parsefactoriesreturns early for them(the lookup uses
safe_getattr, so arbitrary user objects are unaffected).The marker is applied to:
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)ConfigandPytestPluginManagerobjects22 holders skipped per session build in total. Modules that do define
fixtures (
fixtures— including thepytestconfigfixture,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_fixtureswalks every marked holder and fails if any of them actually defines a
fixture.
Measured
Per session build + collect-only run (default plugin set):
dir()names scanned)_check_for_wrapped_fixturevalidationstesting/test_config.py(-n 8, pytester-heavy, single runs each):31.67s → 29.80s.
--fixturesoutput verified identical (modulo shiftedline numbers from the added marker lines).
Tests
test_no_fixtures_opt_out_holders_define_no_fixtures: passestesting/test_meta.py,testing/test_pluginmanager.py: 108 passed, 1 skippedtesting/python/fixtures.py: 242 passed, 3 xfailedtesting/test_config.py: 290 passed, 1 xfailedtesting/test_doctest.py,testing/test_conftest.py: 202 passed, 1 skipped, 1 xfailedChangelog 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.