Skip to content

tests: harden parallel test execution - #967

Merged
yisding merged 2 commits into
mainfrom
agent/pytest-xdist-cleanup
Aug 8, 2026
Merged

tests: harden parallel test execution#967
yisding merged 2 commits into
mainfrom
agent/pytest-xdist-cleanup

Conversation

@yisding

@yisding yisding commented Aug 7, 2026

Copy link
Copy Markdown
Owner

What changed

  • cap -n auto at 8 workers and use per-test load scheduling in socket-free quick and coverage lanes
  • run direct-fork tests in an explicit serial slice without xdist or watchdog helper threads
  • avoid creating pytest-asyncio runners for synchronous tests while retaining async task leak checks
  • consolidate five cold mypy consumer checks into one downstream type-contract test
  • join a test-owned thread and update CI, documentation, validation selectors, and policy guards

Why

The suite mixed xdist workers, direct os.fork() calls, a global async autouse fixture on synchronous tests, and several repeated cold mypy processes. That combination created deadlock risk, noisy teardown behavior, uneven scheduling, and redundant work.

Impact

The quick lane remains broad while excluding process-global and xdist-unsafe tests. Static typing assertions are preserved in one dedicated CI step. The final local quick run completed in 2:44, compared with 3:51 before separating slow and serial work.

Validation

  • quick xdist lane: 8,216 passed, 174 skipped
  • serial direct-fork slice: 5 passed
  • consolidated downstream type contracts: passed
  • focused policy and docs guards: 93 passed
  • full pre-commit suite: passed
  • mypy for src/easycat: passed

Summary by CodeRabbit

  • Bug Fixes

    • Improved validation reliability for fork-based, serial, and asynchronous test scenarios.
    • Reduced unnecessary resource usage during test execution and improved handling of worker limits.
  • Documentation

    • Clarified testing workflows, validation markers, parallel execution, fork safety, and contributor guidance.
  • Tests

    • Added downstream type-contract coverage to catch consumer-facing typing regressions.
    • Improved test reporting with dedicated results for specialized validation checks.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yisding, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f246a910-d7d7-4dc3-9a93-7180468e9285

📥 Commits

Reviewing files that changed from the base of the PR and between 7c49876 and 31f9a08.

📒 Files selected for processing (9)
  • .github/workflows/ci.yml
  • .github/workflows/nightly-validation.yml
  • CONTRIBUTING.md
  • docs/reference/validation-vocabulary.md
  • justfile
  • src/easycat/validation/_slice_runner.py
  • tests/cli/test_validate_runner.py
  • tests/test_pytest_harness_policy.py
  • tests/typecheck/test_consumer_contracts.py
📝 Walkthrough

Walkthrough

The PR separates serial tests from xdist runs, adds serial marker policy and fork-test safeguards, changes scheduling modes, caps automatic workers, scopes asyncio leak checks, updates CI lanes, and adds downstream consumer type-contract validation.

Changes

Validation harness and execution lanes

Layer / File(s) Summary
Pytest harness policy
pyproject.toml, tests/conftest.py, tests/test_pytest_harness_policy.py, tests/test_validation_markers.py
Pytest registers and excludes serial tests. Automatic xdist workers are capped at eight with an environment override. Asyncio leak checks activate only for applicable tests.
Serial test classification and fork safety
tests/runtime/test_artifacts.py, tests/runtime/test_crash_sweep.py, tests/vad/test_silero.py, tests/core/test_cancel_token.py, docs/development/..., docs/reference/..., CONTRIBUTING.md
Fork-dependent tests use serial and zero-timeout markers. Documentation defines direct-fork execution and serial-test rules.
Validation commands and CI lanes
.github/workflows/*, justfile, src/easycat/validation/_slice_runner.py, tests/cli/test_validate_runner.py, tests/_pytest_targets.py, CONTRIBUTING.md
Full, fast, quick, coverage, and nightly commands use separate xdist policies. Serial tests run in dedicated commands with separate JUnit reports.
Downstream consumer type contracts
tests/typecheck/test_consumer_contracts.py, tests/config/test_easyconfig_preset_typing.py, tests/test_public_api.py, tests/test_session_event_typing.py, tests/test_voice_app_typing.py
The typecheck suite validates generated valid and invalid consumers with one cold mypy run. Older subprocess-based typing checks were removed.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CIWorkflow
  participant PytestXdist
  participant SerialPytest
  participant JUnitArtifacts
  CIWorkflow->>PytestXdist: Run non-serial tests with selected xdist distribution
  CIWorkflow->>SerialPytest: Run serial fork tests without xdist
  PytestXdist->>JUnitArtifacts: Write parallel JUnit report
  SerialPytest->>JUnitArtifacts: Write serial JUnit report
Loading

Possibly related PRs

Poem

I hop through lanes, both fast and slow,
While serial forks run below.
Type contracts bloom in my test garden,
And JUnit reports stand guard at the warren.
Squeak—safe workers, clear flow,
A tidy validation show!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes to make parallel test execution safer and more reliable.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/pytest-xdist-cleanup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@yisding
yisding marked this pull request as ready for review August 8, 2026 05:13

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7c49876559

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tests/typecheck/test_consumer_contracts.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 99-108: Add tests/core/test_cancel_token.py to the serial pytest
command in both serial validation lanes: .github/workflows/ci.yml lines 99-108
and .github/workflows/nightly-validation.yml lines 46-56. Keep the existing test
selections and serial marker unchanged.

In `@justfile`:
- Around line 36-41: Update the pytest marker selectors used by test-fast and
cov to exclude the documented latency marker alongside the other
timing-sensitive lanes, or revise the test-fast comment to say that only socket
tests are excluded. Keep the comment, marker expressions, and documented
validation behavior consistent.
- Around line 24-29: The serial pytest command in the justfile only disables
faulthandler, not the pytest-timeout plugin. Update the command using the
existing serial test invocation to override pytest-timeout with timeout=0, and
ensure every serial test explicitly configures its required timeout; otherwise
revise the documentation to avoid claiming pytest helper threads are disabled.

In `@tests/test_pytest_harness_policy.py`:
- Around line 72-75: Extend test_xdist_auto_workers_respect_explicit_override
with cases for a non-integer override and numeric values below 1. For each case,
set PYTEST_XDIST_AUTO_NUM_WORKERS and assert that _xdist_auto_worker_count()
raises pytest.UsageError, covering the validation path in conftest.py.

In `@tests/typecheck/test_consumer_contracts.py`:
- Around line 89-91: Add the pytest.mark.integration_external decorator to
test_downstream_consumer_type_contracts, alongside its existing slow and timeout
markers, so the locally spawned mypy process is classified as an external
integration test.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1f5b0cf3-019c-4c34-ba5d-2423e943c109

📥 Commits

Reviewing files that changed from the base of the PR and between 5c22bb1 and 7c49876.

📒 Files selected for processing (22)
  • .github/workflows/ci.yml
  • .github/workflows/nightly-validation.yml
  • CONTRIBUTING.md
  • docs/development/08-development-and-testing.md
  • docs/reference/validation-vocabulary.md
  • justfile
  • pyproject.toml
  • src/easycat/validation/_slice_runner.py
  • tests/_pytest_targets.py
  • tests/cli/test_validate_runner.py
  • tests/config/test_easyconfig_preset_typing.py
  • tests/conftest.py
  • tests/core/test_cancel_token.py
  • tests/runtime/test_artifacts.py
  • tests/runtime/test_crash_sweep.py
  • tests/test_public_api.py
  • tests/test_pytest_harness_policy.py
  • tests/test_session_event_typing.py
  • tests/test_validation_markers.py
  • tests/test_voice_app_typing.py
  • tests/typecheck/test_consumer_contracts.py
  • tests/vad/test_silero.py
💤 Files with no reviewable changes (4)
  • tests/test_session_event_typing.py
  • tests/test_voice_app_typing.py
  • tests/config/test_easyconfig_preset_typing.py
  • tests/test_public_api.py

Comment thread .github/workflows/ci.yml
Comment thread justfile Outdated
Comment thread justfile Outdated
Comment thread tests/test_pytest_harness_policy.py
Comment thread tests/typecheck/test_consumer_contracts.py
- Render the scaffold agent.py beside server.py in the consumer contract
  test so mypy resolves 'from agent import make_agent' instead of
  silently degrading it to Any under ignore_missing_imports.
- Disable pytest-timeout (-o timeout=0) in every serial lane so no
  helper thread can start before a direct-fork test, even for a future
  serial test that forgets its own timeout(0) marker.
- Exclude the documented 'latency' marker from test-fast, cov, the
  quick validation slice, and the CI coverage job so the
  'timing-sensitive lanes are excluded' claim holds by construction.
- Cover invalid PYTEST_XDIST_AUTO_NUM_WORKERS overrides.
- Guard that the CI serial file lists cover every serial-marked file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@yisding
yisding merged commit 50a2b52 into main Aug 8, 2026
18 checks passed
@yisding
yisding deleted the agent/pytest-xdist-cleanup branch August 8, 2026 05:34
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.

1 participant