Defer worker recycling to end of unit to preserve scope fixture teardown#106
Merged
thejchap merged 1 commit intoMay 9, 2026
Merged
Conversation
Recycling inside `run_single_test` could fire mid-unit, dropping the live process before `handle_unit`'s `finalize_hooks` loop ran — and that loop is gated on `state.process.as_mut()`, so per="scope" fixture teardown was silently skipped (or run on a fresh worker's freshly re-imported fixtures, double-counting setup). Move the recycle check to after `finalize_hooks` in `handle_unit`. Adjusts the existing recycle test to submit one unit per test (so the end-of-unit check fires at the threshold) and adds a coverage test that crosses the threshold inside a single unit with a per="scope" fixture, asserting setup and teardown each run exactly once. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
thejchap
added a commit
that referenced
this pull request
May 13, 2026
Recycling inside `run_single_test` could fire mid-unit, dropping the live process before `handle_unit`'s `finalize_hooks` loop ran — and that loop is gated on `state.process.as_mut()`, so per="scope" fixture teardown was silently skipped (or run on a fresh worker's freshly re-imported fixtures, double-counting setup). Move the recycle check to after `finalize_hooks` in `handle_unit`. Adjusts the existing recycle test to submit one unit per test (so the end-of-unit check fires at the threshold) and adds a coverage test that crosses the threshold inside a single unit with a per="scope" fixture, asserting setup and teardown each run exactly once. Co-authored-by: Claude <noreply@anthropic.com>
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.
Summary
This change moves worker process recycling from the end of individual tests to the end of each work unit, ensuring that
per="scope"fixture teardown is not skipped when a worker reaches the recycling threshold.Key Changes
run_single_test()tohandle_unit(), placing it afterfinalize_hooks()completesworker_recycles_after_max_teststo submit one test per unit instead of batching tests, allowing the recycling check to fire as soon as the threshold is crossedrecycle_does_not_skip_scope_fixture_teardownto verify that scope fixture setup and teardown counts remain balanced (1:1) even when recycling occurs mid-unitImplementation Details
The recycling logic checks if a worker process should be recycled (after
MAX_TESTS_PER_WORKERtests) and gracefully shuts it down. Previously, this happened immediately after each test, which could drop the process beforefinalize_hooks()ran, leaving scope fixtures without their teardown calls. The new placement ensures the complete unit lifecycle (including all fixture teardowns) completes before recycling occurs. The next unit assigned to the worker will triggerensure_worker()to spawn a fresh process and replay cached hooks, following the same path as crash recovery.https://claude.ai/code/session_0143AyVfzSvwh3SCUbZxRUJ3