This project demonstrates how to use egui_kittest for testing egui applications. It includes a responsive demo app and comprehensive tests across semantic, geometry, and snapshot styles.
src/lib.rs– The demo application (DemoApp) with responsive layoutsrc/main.rs– Binary entry point to run the demotests/app_tests.rs– App-focused functional tests (inputs, dialogs, scrolling)tests/integration_tests.rs– Wider interaction and responsive assertionstests/snapshot_tests.rs– Narrow/medium/wide snapshots + fit_contentstests/a11y_keyboard_tests.rs– Accessibility/keyboard, geometry, scroll-to-viewtests/snapshots/– Snapshot reference images
- Responsive layout:
- Wide: resizable SidePanel + CentralPanel
- Narrow (< 600 px): stacked layout
- Overflow-safe: left and central content are wrapped in
ScrollArea::vertical - Adaptive grid of “Card” items with column thresholds:
- width >= 900 → 3 columns
- width >= 600 → 2 columns
- else → 1 column
- Form: name (TextInput) and age (SpinButton via DragValue)
- Counter with increment/decrement
- Modal dialog with Yes/No
- Semantic labels used by tests:
Layout: StackedorLayout: Side+CentralColumns: {n}Scale: {n}%,Scale bucket: Small|Medium|Large,Scaling mode: Zoom|Style
- Zoom-based scaling (default): uses
Context::set_zoom_factorwith discrete buckets to avoid oscillations and repaint loops.- < 600 → 0.85x, < 900 → 1.00x, < 1280 → 1.25x, ≥ 1280 → 1.50x
- Style-based scaling: leaves zoom at 1.0 and scales typography/spacing from a captured baseline
Style(idempotent) using discrete buckets.- < 600 → 0.95x, < 900 → 1.15x, < 1280 → 1.35x, ≥ 1280 → 1.60x
- Toggle via View → “Scaling strategy” (Zoom-based / Style-based). The current mode is also shown in-content as
Scaling mode: …. - Breakpoints (stacking, columns, and bucket labels) use physical window width (points × pixels_per_point) so they’re stable across DPI and independent of zoom.
- Semantic queries with AccessKit roles and labels:
get_by_role,get_by_label,get_by_value - Keyboard/focus interactions:
.focus(),harness.key_press,.type_text() - Geometry checks using
.rect()to assert layout order/positions - Scroll reachability:
scroll_to_me()to bring off-screen content into view - Window resizing in tests with
Harness::builder().with_size(..)andharness.set_size(..) - Image snapshots at multiple sizes and
fit_contents()flows - CI-friendly: stable labels; minimal, focused snapshots
- Scaling coverage: tests assert that
Scale: …%is non-decreasing with width,Scale buckettransitions at 600/900/900+ thresholds, wide geometry grows with scale, and breakpoints remain stable across scaling modes.
To run the demo application:
cargo runTo run all tests:
cargo testTo run specific test files:
# Run integration tests
cargo test --test integration_tests
# Run app-specific tests
cargo test --test app_tests
# Run accessibility/keyboard tests
cargo test --test a11y_keyboard_testsTo run tests with output:
cargo test -- --nocaptureThis repo enables egui_kittest's snapshot testing behind the wgpu and snapshot features.
- Images are written to
tests/snapshots/on first run. - To update snapshots, run with the env var:
UPDATE_SNAPSHOTS=true cargo testAdd these to .gitignore to avoid noise from diffs/temporary images:
**/tests/snapshots/**/*.diff.png
**/tests/snapshots/**/*.new.pngNotes:
- Snapshots can differ by OS/driver. Our CI runs snapshot steps on macOS and skips them on Linux.
- Prefer semantic and geometry assertions for behavior; keep snapshots small and stable.
Harness::new_ui()- For testing UI closuresHarness::new()- For testing full egui contexts
get_by_label()/query_by_label()– by exact label textget_by_role()/query_by_role()– by AccessKit roleget_by_value()/query_by_value()– by value text
.click()– Simulate button clicks.focus()and.type_text()– Keyboard input into fieldsharness.key_press(..)– Simulate key presses.scroll_to_me()– Ensure off-screen nodes are brought into view
- Frame stepping with
harness.run() - State verification between interactions
- Dialog/window lifecycle testing
- Complex user workflows
egui– The immediate mode GUI frameworkeframe– Application framework for eguiegui_kittest– Testing framework for egui applicationstokio– Async runtime (for some tests)
- Tests use the latest version of egui_kittest (0.32.0)
- The demo app is designed to be simple but cover common UI patterns
- Tests demonstrate both positive and negative test cases
- All tests are headless and don't require a display server
- Make overflow content scrollable with
egui::ScrollArea::vertical(). - Account for side panels when asserting grid column counts; central width is less than window width.
- Use stable, semantic labels (e.g.,
Layout: …,Columns: …) to make tests robust. - Prefer semantic/geometry assertions over large snapshots; keep images minimal and focused.
- Test responsive behavior at representative widths:
- 360 px: stacked + 1 column
- 820 px: side+central + 2 columns (accounts for SidePanel width)
- 1280 px: 3 columns
- Use physical width (points × pixels_per_point) for breakpoints so layout is stable across DPI and independent of zoom.
- When writing tests that change scaling modes, prefer asserting the semantic
Scaling mode: …label. For breakpoint stability across modes, you can setapp.scaling_modedirectly before building a harness for determinism.
#[test]
fn test_example() {
let mut harness = Harness::new_ui(|ui| {
// Your UI code here
if ui.button("Click me").clicked() {
// Handle click
}
});
// Test interactions
harness.get_by_label("Click me").click();
harness.run();
// Verify results
harness.get_by_label("Expected result");
}This project serves as a comprehensive reference for testing egui applications with egui_kittest.