Testing with insta snapshots
Summary
Section titled “Summary”Ratatui UIs can be tested by rendering into a fixed-size TestBackend and
snapshotting the backend buffer with insta.
Key Ideas
Section titled “Key Ideas”- Snapshot tests fit visual terminal output: Instead of manually asserting every cell, render the UI once and compare future output against the saved terminal buffer.
- Use deterministic terminal dimensions: The recipe uses a fixed
80x20TestBackend; stable sizes make snapshots reproducible. - Keep rendering testable: The app or widget should expose a render path
that can draw into a
Framewithout requiring a real terminal. - Review changes intentionally: When output changes, use
cargo insta reviewto inspect and accept the new snapshot.
Claims & Evidence
Section titled “Claims & Evidence”| Claim | Support | Caveat / Confidence |
|---|---|---|
| Snapshot tests reduce brittle manual visual assertions. | The recipe positions snapshots as a way to capture reference values once and compare future runs. | High. Still needs focused state setup so snapshots do not become huge and noisy. |
TestBackend is the core Ratatui testing primitive. |
The example builds Terminal::new(TestBackend::new(80, 20)), draws the app, then snapshots terminal.backend(). |
High. |
Snapshot files live under snapshots/. |
The recipe shows generated .snap files containing the rendered terminal rows. |
High. Exact path depends on module/test names. |
| Snapshot review is part of the workflow. | The recipe recommends cargo insta review when UI changes are intentional. |
High. |
Important Terms
Section titled “Important Terms”| Term | Meaning |
|---|---|
TestBackend |
Ratatui backend that stores rendered cells in memory for tests. |
insta |
Rust snapshot-testing crate used to compare rendered output. |
cargo-insta |
CLI helper for reviewing and accepting snapshot changes. |
| Snapshot | Saved expected output used as the comparison target for future test runs. |
Open Questions
Section titled “Open Questions”- Why should TUI snapshot tests use fixed terminal dimensions?
- Recommendation: Use fixed dimensions so layout changes are intentional and snapshot diffs are attributable.
- What object should be passed to
assert_snapshot!after drawing a Ratatui UI?- Recommendation: Snapshot the rendered buffer or a stable row/frame representation rather than terminal I/O.
- When should
cargo insta reviewbe used?- Recommendation: Use
cargo insta reviewonly after verifying the visual change is intended and behaviorally correct.
- Recommendation: Use
- Which behaviors belong in pure state tests instead of snapshots?
- Recommendation: Put update logic, event transitions, and data reduction in pure tests, leaving visual wrapping and layout to snapshots.
Connections
Section titled “Connections”- Related ideas: Elm-style update tests, Ratatui
TestBackend, render functions separated from terminal setup. - Related sources: Ratatui Elm architecture notes, Ratatui terminal/event-handler recipe.
- Conceptual uses: normal-width chat layout, narrow layout with hidden sidebar, transcript entries for assistant/tool/reasoning states, provider error rendering.
Open Questions
Section titled “Open Questions”- Should
thndrssnapshot whole screens or smaller render regions first?- Recommendation: Prefer focused region snapshots plus pure state tests, expanding to whole-screen snapshots only for stable end-to-end layouts.
- Do we want
instaredactions for timestamps/session IDs once persistence exists?- Recommendation: Add redactions for volatile identifiers as soon as snapshots include persisted session or timing data.
- Should CI require committed snapshots immediately, or only after the layout
stabilizes?
- Recommendation: Require committed snapshots for stable regions and keep volatile experiments out of CI until their layout settles.
Notable Quotes
Section titled “Notable Quotes”“Use a consistent terminal size”