Skip to content

tests: speed up unit tests#5980

Merged
Bobronium merged 5 commits into
mainfrom
arseny/concurrent-tests
Jun 9, 2026
Merged

tests: speed up unit tests#5980
Bobronium merged 5 commits into
mainfrom
arseny/concurrent-tests

Conversation

@Bobronium

@Bobronium Bobronium commented Jun 5, 2026

Copy link
Copy Markdown
Member

Running pytest --unit with these changes goes from 3 minutes 44 seconds to just 30 seconds.

How does it work

Virtual time

Takes advantage of the fact that many of the tests rely on asyncio.sleep() to synchronize events in the loop. It unties it from the real time so that await asyncio.sleep(60) returns instantly with loop.time() reporting 60 seconds passed. time.time() is then patched to report loop time. This brings down test_agent_session.py test time form 90 seconds to just 1 second without any modifications to the test itself.

  • To disable globally --real-time option can be used.
  • To enable/disable per-module or per-test pytest.mark.virtual_time/.real_time can be used.

Concurrent tests

Tests with real I/O are groupped by their module and executed in a shared event loop. This shrinks wall time of the whole module to wall time of the slowest test + raw compute. contextvars are used to preserve input capture and track leaked tasks.

  • To disable concurrent execution, --no-concurrent option can be used.
  • To enable/disable per-module or per-test, pytest.mark.no_concurrent/.no_concurrent can be used.

Changes

  • Add pytest-asyncio-concurrent — gives the speedup for I/O bound tests
  • Add tests/concurrent.py that extends on pytest-asyncio-concurrent and adds crucial features:
    • Captures stdout/stderr and reports on failure (same as pytest)
    • Allows leaked tasks detection in concurrent mode (so that fail_on_leaked_tasks continues to work)
    • adds --concurrent/--no-concurrent options
    • Adds live progress
  • Add tests/virtual_time.py that provides instant and deterministic asyncio clock for time-bound execution

Changes to the tests sources

  • 04fe6cb: Add concurrent/virtual_time markers to tests modules
  • a8f5be0: Tighten timings in test_audio_decoder.py, test_ipc.pt and test_room.py
  • 396bce8: Make test_async_channel and test_proc_pool_launch_job_raises_when_all_spawns_fail in test_ipc.py safe to run concurrently

@Bobronium Bobronium force-pushed the arseny/concurrent-tests branch 2 times, most recently from a8f9f03 to d151c7d Compare June 8, 2026 10:50
@livekit livekit deleted a comment from CLAassistant Jun 8, 2026
@Bobronium Bobronium force-pushed the arseny/concurrent-tests branch 2 times, most recently from cccb2b0 to 927a04f Compare June 8, 2026 12:32
Run a module's async tests together on one event loop via asyncio.gather, with
per-test output/log/caplog capture and leaked-task attribution keyed on a
contextvar, a live progress line, and fd-level capture so a spawned child's
stdout can't corrupt it. Opt in per test with @pytest.mark.concurrent (and out
with @pytest.mark.no_concurrent); --concurrent / --no-concurrent / LK_TEST_CONCURRENCY
flip the default. Wired in via pyproject (-p tests.concurrency) and conftest.

Co-authored-by: Claude <noreply@anthropic.com>

https://claude.ai/code/session_01UFjbSTeVMYyRhLjZmcVRGd
@Bobronium Bobronium force-pushed the arseny/concurrent-tests branch from 927a04f to 396bce8 Compare June 8, 2026 12:53
Bobronium added 4 commits June 8, 2026 14:41
@pytest.mark.virtual_time runs a test on a SelectorEventLoop whose clock jumps
to the next scheduled timer instead of sleeping, so timing-coupled voice tests
finish in ~0 wall time and deterministically. time.time()/perf_counter() and
captured default_factory clocks are scoped to the running loop for the marked
test only; off-loop callers keep the real clock. real_time opts a test out.

Co-authored-by: Claude <noreply@anthropic.com>

https://claude.ai/code/session_01UFjbSTeVMYyRhLjZmcVRGd
Mark each async unit module concurrent or no_concurrent, and the timing-coupled
voice modules virtual_time + no_concurrent, so they run on the deterministic
loop sequentially. Sync-only modules stay plain unit.

Co-authored-by: Claude <noreply@anthropic.com>

https://claude.ai/code/session_01UFjbSTeVMYyRhLjZmcVRGd
Trim fixed waits now that these run fast: test_ipc shutdown/aclose guardrails
(_SESSION_ACLOSE_TIMEOUT 2->0.5s, simulated shutdown 1->0.3s) and its channel
teardown sleep; test_audio_decoder reader warm-up 1->0.1s; test_room reconnect
audio-continuity windows 1.5->1.0s.

Co-authored-by: Claude <noreply@anthropic.com>

https://claude.ai/code/session_01UFjbSTeVMYyRhLjZmcVRGd
Run the blocking proc.join() in an executor so it can't stall the shared loop,
and inject the all-spawns-fail case (#5868) through a real init fn that raises
instead of monkeypatching ProcJobExecutor process-wide.

Co-authored-by: Claude <noreply@anthropic.com>

https://claude.ai/code/session_01UFjbSTeVMYyRhLjZmcVRGd
@Bobronium Bobronium force-pushed the arseny/concurrent-tests branch from 396bce8 to 0973861 Compare June 8, 2026 14:42
@Bobronium Bobronium changed the title tests: speed up unit tests by running them concurrently tests: speed up unit tests Jun 8, 2026
@Bobronium Bobronium marked this pull request as ready for review June 8, 2026 14:54
@chenghao-mou chenghao-mou requested a review from a team June 8, 2026 14:55

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 6 additional findings.

Open in Devin Review

@theomonnom theomonnom left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm!

@Bobronium Bobronium merged commit 8c71144 into main Jun 9, 2026
48 of 50 checks passed
@Bobronium Bobronium deleted the arseny/concurrent-tests branch June 9, 2026 09:23
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.

2 participants