Skip to content

Fix fixture finalizers being skipped when setup is interrupted - #15092

Closed
Dextheking1 wants to merge 4 commits into
pytest-dev:mainfrom
Dextheking1:fix/15067-fixture-finalizers-on-interrupt
Closed

Dextheking1 wants to merge 4 commits into
pytest-dev:mainfrom
Dextheking1:fix/15067-fixture-finalizers-on-interrupt

Conversation

@Dextheking1

Copy link
Copy Markdown

Fixes #15067.

When fixture setup is interrupted by something that is not a test outcome -- e.g. KeyboardInterrupt from a fail-fast plugin or a manual interrupt -- pytest_fixture_setup never assigned cached_result. FixtureDef.finish() treats cached_result is None as "already finished" and returns early, so finalizers registered via request.addfinalizer() before the interruption were silently skipped, even though the docs say a finalizer runs once added, even if the fixture raises afterwards.

The fix records the interruption in cached_result (a new except BaseException branch alongside except TEST_OUTCOME), so teardown still runs the registered finalizers. On later cache hits the recorded exception is re-raised as before, so no stale value can leak.

Testing:

  • New regression test testing/python/fixtures.py::TestRequestBasic::test_request_addfinalizer_interrupted_setup runs an inner pytest in a subprocess whose fixture registers a finalizer and then raises KeyboardInterrupt; it asserts the run exits interrupted and the finalizer marker file is created. Verified failing before the fix, passing after.
  • Full testing/python/fixtures.py: 243 passed, 1 skipped, 2 xfailed.

Changelog entry added per the towncrier convention (changelog/15067.bugfix.rst).

Record interruptions (e.g. KeyboardInterrupt) that escape
pytest_fixture_setup in cached_result so FixtureDef.finish() still
runs finalizers registered via request.addfinalizer() during
teardown, as documented. Fixes pytest-dev#15067.
@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Sep 23, 2026
pre-commit-ci Bot and others added 3 commits September 23, 2026 16:59
The subprocess regression test cannot be seen by coverage, so the new
except BaseException branch in pytest_fixture_setup showed 0% patch
coverage. This in-process variant runs the same interrupted-setup
scenario in-process (with no_reraise_ctrlc=True) so coverage observes the
new branch.
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 finalizers are skipped when setup is interrupted before cached_result is assigned

2 participants