Snapshot Testing
Relevant source files
The following files were used as context for generating this wiki page:
Snapshot testing in the QQcode project provides a mechanism for verifying the visual integrity and behavior of the Textual-based Terminal User Interface (TUI). By capturing pixel-to-pixel comparisons of the application state, the system ensures that UI components, animations, and layouts remain consistent across changes.
The framework utilizes pytest-textual-snapshot to perform these comparisons, relying on a specialized "base app" that stubs external dependencies like LLM backends to ensure deterministic results. Sources: pyproject.toml:94, tests/snapshots/base_snapshot_test_app.py:12-20
Architecture and Infrastructure
The snapshot testing infrastructure is built upon a specialized version of the main TUI application, designed to eliminate non-deterministic UI elements that would otherwise cause snapshot mismatches.
Base Snapshot Test App
The BaseSnapshotTestApp extends the standard VibeApp. It is configured to remove "interference" during comparisons by:
- Stubbing LLMs: Injecting a
FakeBackendto prevent actual API calls. - Disabling Animations: Turning off the welcome banner animation.
- Static Metadata: Forcing a static value for the displayed working directory.
- Cursor Management: Hiding the chat input cursor to avoid mismatches caused by blinking animations.
Sources: tests/snapshots/base_snapshot_test_app.py:12-25, tests/snapshots/base_snapshot_test_app.py:32-45
Testing Components
| Component | Description |
|---|---|
pytest-textual-snapshot | The core dependency used to capture and compare terminal snapshots. |
FakeBackend | A stub implementation of the LLM backend used to provide predictable responses. |
SnapCompare | A utility (likely a fixture) used to execute the comparison between current UI state and saved snapshots. |
TextAreaTheme | Used to create a hidden_cursor theme for deterministic text input snapshots. |
Sources: pyproject.toml:94, tests/snapshots/base_snapshot_test_app.py:23, tests/snapshots/base_snapshot_test_app.py:48-52
Snapshot Execution Flow
Snapshot tests follow a specific lifecycle where the application is initialized with a controlled configuration, modified to a specific state (e.g., mounting a message or triggering a notification), and then compared against a reference image.
The following diagram illustrates the flow of a snapshot test execution:
This flow ensures that the TUI environment is completely isolated from the live environment. Sources: tests/snapshots/base_snapshot_test_app.py:12-20, tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py:23-30
Configuration and Tooling
Snapshot tests use a restricted VibeConfig to ensure stability.
Default Snapshot Configuration
The configuration emphasizes disabling features that involve timing or external state:
session_logging: Disabled (enabled=False).textual_theme: Hardcoded to "gruvbox".disable_welcome_banner_animation: Set toTrue.enable_update_checks: Set toFalse(unless explicitly testing the update notifier).
Sources: tests/snapshots/base_snapshot_test_app.py:12-28
Development Commands
Snapshot tests are executed as part of the standard test suite using uv.
# Run all tests including snapshots
uv run pytest
# Run specific snapshot test files
uv run pytest tests/snapshots/test_ui_snapshot_release_update_notification.py
Sources: CLAUDE.md:17-23
Specific Test Scenarios
The project implements snapshots for complex UI behaviors that are difficult to verify with unit tests alone.
Release Update Notifications
Tests verify that the VersionUpdate logic correctly displays notifications. A SnapshotTestAppWithUpdate is used, which overrides the default config to enable update checks and injects a FakeVersionUpdateGateway with a spoofed latest version.
Sources: tests/snapshots/test_ui_snapshot_release_update_notification.py:10-21
Code Block Scrolling
Snapshots verify that long code blocks within AssistantMessage widgets support horizontal scrolling. The test mounts an AssistantMessage containing a long Python print statement, triggers a relative scroll action on the MarkdownFence widget, and then captures the snapshot.
Sources: tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py:12-32
Class Relationships
The snapshot testing suite utilizes inheritance to share the setup logic for the TUI environment.
The BaseSnapshotTestApp serves as the foundation for all visual regression testing. Sources: tests/snapshots/base_snapshot_test_app.py:32-34, tests/snapshots/test_ui_snapshot_release_update_notification.py:10
Conclusion
Snapshot testing in QQcode is a critical component of the CI/CD pipeline, ensuring that the Textual TUI remains visually consistent and functional. By utilizing the BaseSnapshotTestApp to eliminate non-determinism and pytest-textual-snapshot for pixel-perfect validation, the project maintains a high standard for user interface reliability.