with one click
gpui-test
Use when writing, debugging, or reproducing GPUI tests in Zed, including gpui::test arguments, TestAppContext parameters, scheduler seeds, ITERATIONS/SEED reproduction, parking failures, and pending task traces.
Use when writing, debugging, or reproducing GPUI tests in Zed, including gpui::test arguments, TestAppContext parameters, scheduler seeds, ITERATIONS/SEED reproduction, parking failures, and pending task traces.
Cherry-pick one or more merged PRs and/or commits into Zed's `preview` or `stable` release branch. Use this whenever the user mentions cherry-picking to preview/stable, a failed cherry-pick run, or wants to manually port fix(es) into a release branch.
Helps you create new agent skills for Zed. Use this to create a skill, ask about SKILLs.md, or package reusable agent instructions.
Write clear, developer-first copy for Zed — leading with facts, grounded in craft.
Remove signs of AI-generated writing from text. Use after drafting to make copy sound more natural and human-written. Based on Wikipedia's "Signs of AI writing" guide.
Write clear, developer-first copy for Zed — leading with facts, grounded in craft.
| name | gpui-test |
| description | Use when writing, debugging, or reproducing GPUI tests in Zed, including gpui::test arguments, TestAppContext parameters, scheduler seeds, ITERATIONS/SEED reproduction, parking failures, and pending task traces. |
Use this skill when the user asks about #[gpui::test], GPUI test seeds or iterations, deterministic scheduler failures, parking/pending task failures, or how to reproduce a flaky GPUI test.
#[gpui::test] does#[gpui::test] expands to a normal Rust #[test], so it runs under standard Rust test runners such as cargo test and cargo nextest.
It wraps the body in GPUI's deterministic test dispatcher/scheduler and can run the same test multiple times with different seeds. The seed controls scheduler task interleavings and any StdRng argument injected into the test.
The macro supports both synchronous and asynchronous tests.
The macro recognizes arguments by type name:
| Test kind | Supported arguments |
|---|---|
| Sync and async | &TestAppContext, &mut TestAppContext, StdRng |
| Async only | BackgroundExecutor |
| Sync only | &App, &mut App |
StdRng is seeded from the current GPUI test seed, and BackgroundExecutor is backed by the same deterministic test dispatcher.
Use these forms on #[gpui::test(arguments)]:
0, unless SEED is set.seed = N: adds a single explicit seed.seeds(...): adds multiple explicit seeds.iterations = N: runs sequential seeds starting at 0 by default.retries = N: retries a failing run up to N times before surfacing the failure.on_failure = "path::to::function": calls the function after final failure, before resuming the panic.iterations can be combined with explicit seed / seeds; explicit seeds are appended to the 0..iterations range.SEED environment variable is set, it takes precedence over explicit seeds.SEED=N and ITERATIONS=M or iterations = M, the harness runs seeds N..N+M.SEED=<u64> — chooses the scheduler seed. Use this to reproduce a failure printed as failing seed: N. It also seeds injected StdRng arguments. For #[gpui::property_test], it controls the scheduler seed and GPUI applies it to the proptest config for deterministic case generation.ITERATIONS=<usize> — overrides the iterations = ... value at runtime. Use to sweep many seeds without editing the test.PENDING_TRACES=1 or PENDING_TRACES=true — captures and prints pending task traces when the test scheduler panics with Parking forbidden. Use this when run_until_parked() or teardown reports pending work.GPUI_RUN_UNTIL_PARKED_LOG=1 — logs when allow_parking() is enabled. Use to find tests that explicitly permit parking/pending work.DEBUG_SCHEDULER=1 — prints scheduler clock/timer debugging from scheduler::TestScheduler.SCHEDULER_NONINTERACTIVE=1 — suppresses interactive seed progress output in scheduler::TestScheduler::many. This does not affect the #[gpui::test] harness path.RUST_BACKTRACE=1 or RUST_BACKTRACE=full — show panic backtraces.RUST_LOG=<filter> — enable logs when the test initializes logging.ZED_HEADLESS=1 — forces GPUI platform guessing toward headless mode; useful for tests that otherwise interact with platform/window setup.Prefer env vars over editing the test when narrowing a reproduction.
Identify the crate/package and test name.
Run the narrowest test filter first, skip to 3. if a failing seed is known.
cargo -q test -p <crate-name> <test_name> -- --nocapture
If the failure mentions a seed, rerun exactly that seed.
SEED=<seed> cargo -q test -p <crate-name> <test_name> -- --nocapture
If the failure is flaky and no seed is known, sweep seeds.
ITERATIONS=100 cargo -q test -p <crate-name> <test_name> -- --nocapture
When the harness prints failing seed: <seed>, switch to SEED=<seed> for all future debugging.
If the failure is Parking forbidden, rerun with pending traces.
PENDING_TRACES=1 cargo -q test -p <crate-name> <test_name> -- --nocapture
If a failing seed was printed or is already known, include it too:
SEED=<seed> PENDING_TRACES=1 cargo -q test -p <crate-name> <test_name> -- --nocapture
Inspect the pending traces for a task that was spawned but not awaited, detached, completed, or intentionally allowed to park.
If timing or timer advancement is involved, prefer GPUI scheduler timers in tests:
cx.background_executor().timer(duration).await;
Avoid smol::Timer::after(...) in GPUI tests that rely on run_until_parked(), because GPUI's scheduler may not track it.
Minimize the reproduction.
SEED fixed.ITERATIONS to 1 or remove it once a seed is known.StdRng, log or assert the generated scenario after fixing the scheduler seed.Validate the fix.
ITERATIONS=20, if the failure was scheduler-sensitive.Likely caused by a scheduler interleaving or by StdRng-driven test data. Fix SEED, reproduce, and inspect which task or generated scenario differs.
Parking forbiddenUsually means a foreground/background task is still pending when the scheduler expected the test to make progress or finish. Look for:
cx.run_until_parked() after triggering async work in a test.cx.advance_clock(...) to wait for debounced work in a test.Rerun with PENDING_TRACES=1 before changing code.
The scheduler can report activity from an unexpected thread. Look for work escaping GPUI's foreground/background executors, direct thread spawns, or external async runtimes not controlled by the test dispatcher.
Use the failing seed from sweep output. Avoid assuming test order unless the runner is explicitly serial. Check globals, leaked entities/tasks, and state not reset by test initialization.
#[gpui::test] for tests that need TestAppContext, deterministic executors, fake time, or scheduler interleaving coverage.iterations = N when the test is intentionally checking interleavings.StdRng as a test argument when randomized test data should follow the same seed as the scheduler.cx.background_executor().timer(duration).await for delays/timeouts in GPUI tests.retries while fixing a test unless the user explicitly asks or the test already documents why probabilistic tolerance is intentional. Retries can mask the failure instead of fixing it.