As practised (checked 2026-10-01)
- 129 Rust tests: unit tests next to the code, integration tests in
tests/against real SQLite/DuckDB/Turso/redb/RocksDB/HelixDB/LadybugDB files in temp dirs, server-function tests, and component tests with aVirtualDomharness (shell/tests/remote_dialog.rs,shell/tests/server_dialog.rs).- 47 browser suites (Playwright,
packages/web/tests/e2e/*.mjs,run-all.sh) againstdx serveof the web build, Chromium and Firefox; two Android suites over the WebView’s DevTools socket. Setup and rules:packages/web/tests/e2e/README.md.- Not used (despite the tables below):
proptest,insta,cargo nextest,testcontainers,wasm-bindgen-test,vitest, aTestHost/FakeSourcetest utility. The bundles have one unit test (packages/js/milkdown,npm test).- CI (since 2026-10-01,
.github/workflows/ci.yml, Milestone 18 - Implementation Log): rustfmt, the layering rules (tools/check-deps.py),cargo test --workspace,clippy -D warnings, a wasm32 check of the web client, and six browser suites (files rich stores palette shell wiki) againstdx serve. The other 41 suites run locally withrun-all.sh.
A fullstack Dioxus workspace has five different kinds of code, and each is tested differently. Knowing which kind you’re looking at tells you which tool to reach for. The companion note How to Write Tests is the hands-on walkthrough.
The pyramid, mapped to this repo
flowchart TB E2E["E2E: real app in a real browser/webview<br/>few, slow, catch integration + platform bugs"] COMP["Component tests: render rsx! to a string, assert<br/>many, fast, no browser"] SRV["Server-function tests: call the async fn in a tokio test<br/>+ HTTP tests against a running api"] INT["Integration: a Source against a real SQLite/DuckDB/lbug file in a tempdir"] UNIT["Unit: core model, lifting rules, query IR, when-clauses, link resolution<br/>most tests live here; plain #[test]"] E2E --- COMP --- SRV --- INT --- UNIT
| kind of code | where | test with | runs on |
|---|---|---|---|
| Pure logic (model, parsers, lifting, layouts) | core, sources::lift, index::extract, editor-graph::layout | #[test], proptest for invariants, insta snapshots for structures | cargo test native, fast |
Components (rsx!) | ui, editors/* | build a VirtualDom, rebuild_in_place(), dioxus_ssr::render → assert on the HTML string; insta for snapshots | native, no browser |
| Server functions | api | call them as normal async fns under #[tokio::test] with the server feature; HTTP-level tests with reqwest against dx serve/a test server | native |
| Sources / drivers | sources-*, project-fs | integration tests in tests/ with a tempdir DB; containers (testcontainers) for Postgres/Redis/Falkor | native, some need Docker |
| Browser-only behaviour (interop, wasm) | packages/js, wasm paths | wasm-bindgen-test in headless Firefox/Chrome; JS unit tests with vitest for the bundles | wasm |
| Whole app | web, desktop | E2E: headless Firefox screenshot/DOM checks (what we did for the dummy UI); Playwright later | browser |
| Extensions | any | TestHost from ext-api (in-memory sources, recorded calls) | native |
Principles
- Test at the seam you designed. The traits in this project (
Source,CodeEditorBackend,Extension,Layout) exist to be swapped — so they are also where fakes go. AFakeSourceincoretest utils is the single most valuable test fixture in the repo. - Push logic down the pyramid. If a component test needs a database, the logic is in the wrong layer. Components should be thin over signals; test the signal logic with plain functions.
- Snapshot what is structural, assert what is semantic.
instasnapshots for rendered HTML and lifted graphs; explicit asserts for “the FK became an edge from A to B”. - Property tests for the model.
Transactionapply/undo round-trips, deterministic ids (derive(a) == derive(a)),WhenClauseparse/print, layout stability under permutation. - Every platform-gated module gets a compile test.
cargo check -p web --target wasm32-unknown-unknownin CI proves no native crate leaked in (Platform Matrix). - E2E is for integration and platform bugs only. Keep them few; they found both CSS bugs in the dummy UI (P-002 Dioxus mount point and full-height layout, P-003 dioxus-workbench theme variables) that no unit test could.
Tooling
cargo nextestfor parallel, per-test-process runs (a panicking test can’t take the others down; matters with C++ drivers).cargo test --workspace --exclude webfor the native suite; a separate wasm job.cargo clippy --workspace— the repo’sclippy.tomlalready bans holding signal guards across.await; keep it.cargo fmt --check.- CI matrix (planned): linux-native, linux-wasm-check, linux-webkitgtk-e2e, macos-native.
What we test first (Phase 1)
core: ids,PropertyMap,Transactionapply/undo,WhenClause.project-fs: tree building with.gitignore, patch application atomicity, watch coalescing (tempdir +notify).ui: the workbench shell renders the registry’s panels (component snapshot).api:echo(exists) and, once real,query/fetch/applyover aFakeSource.- One E2E: open the web build, assert the workbench and one panel exist.