Skip to content

Testing with insta snapshots

Ratatui UIs can be tested by rendering into a fixed-size TestBackend and snapshotting the backend buffer with insta.

  • 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 80x20 TestBackend; stable sizes make snapshots reproducible.
  • Keep rendering testable: The app or widget should expose a render path that can draw into a Frame without requiring a real terminal.
  • Review changes intentionally: When output changes, use cargo insta review to inspect and accept the new snapshot.
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.
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.
  • 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 review be used?
    • Recommendation: Use cargo insta review only after verifying the visual change is intended and behaviorally correct.
  • 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.
  • 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.
  • Should thndrs snapshot 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 insta redactions 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.

“Use a consistent terminal size”