zed-industries/zed
Testing
How tests are organised
Tests live next to the code they exercise:
- Unit tests as
#[cfg(test)] mod tests { … }blocks at the bottom of source files. - Integration tests in each crate's
tests/directory. - Benchmarks under
*/benches/(e.g.crates/editor/benches,crates/language/benches,crates/project_benchmarks,crates/fs_benchmarks,crates/worktree_benchmarks). - Visual regression tests via
crates/zed/src/visual_test_runner.rsplus thevisual-testsCargo feature on thezedcrate.
Many crates ship a test-support Cargo feature — when set, it pulls in fakes and helpers used by other crates' tests. For example, gpui/test-support provides TestAppContext, VisualTestContext, fake clocks, deterministic runtimes; project/test-support provides a FakeFs, a fake LSP, and so on.
Running tests
cargo test # everything
cargo test -p editor # one crate
cargo test -p editor -- --nocapture # see println! output
cargo test -p editor display_map # filter by name
cargo nextest run -p editor # via nextest if installedCI runs the full suite via .github/workflows/run_tests.yml.
GPUI tests
GPUI provides its own deterministic test harness. See gpui::TestAppContext and gpui::VisualTestContext. Two patterns to know:
#[gpui::test]
async fn test_something(cx: &mut TestAppContext) {
let entity = cx.new(|_cx| MyEntity::default());
entity.update(cx, |this, cx| { /* ... */ });
cx.run_until_parked();
}#[gpui::test]
async fn test_visual(cx: &mut TestAppContext) {
let cx = cx.add_empty_window();
// build UI, take a screenshot, compare to a snapshot
}Timers in tests
From .rules:
Prefer GPUI executor timers over
smol::Timer::after(...)when you need timeouts, delays, or to driverun_until_parked():
- Use
cx.background_executor().timer(duration).await.smol::Timer::after(...)is not tracked by GPUI's scheduler and can deadlockrun_until_parked().
This is the kind of trap that will silently waste an afternoon.
Visual regression tests
Visual tests render UI to an image and diff against a checked-in snapshot. They run under the visual-tests feature:
cargo test -p zed --features visual-testsWhen you intentionally change UI, regenerate the snapshot. The macOS dev guide (docs/src/development/macos.md#visual-regression-tests) covers the workflow.
Test patterns by crate
Areas of the codebase with particularly heavy test coverage:
editor,multi_buffer,text,rope— many tests, often randomized fuzzing for invariants.project— usesFakeFsto simulate a filesystem.language— Tree-sitter parsing and language-detection coverage.collab— full-stack integration tests against a real Postgres incrates/collab/tests.lsp,dap— protocol-level tests with mocked transports.
Mocking and fakes
FakeFs(fs::FakeFs) — in-memory filesystem used by the project tests.FakeHttpClient(http_client) — programmable HTTP responses.- Test-support features in many crates expose deterministic versions of otherwise non-deterministic state.
Coverage expectations
The project does not enforce a numeric coverage threshold. The cultural expectation is:
- Bugs come with a regression test that fails before the fix and passes after.
- New features come with tests for the happy path and at least the obvious failure modes.
- UI work comes with visual regression coverage where reasonable.
Performance regression checks
script/compare-perf and .github/workflows/compare_perf.yml track performance-sensitive paths. The benchmark crates (*/benches/*, project_benchmarks, worktree_benchmarks, fs_benchmarks) feed into these.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.