跳到正文
cccskills
免费在 GitHub 公开

tui-snapshot-tester

Snapshot testing for terminal UI apps (TUIs) - captures rendered terminal frames as deterministic SVG / text snapshots, diffs them on every run, surfaces a reviewable HTML report on failure, and supports `--snapshot-update` to accept changes intentionally. Wraps `pytest-textual-snapshot` for Python Textual apps; provides equivalent recipes for Ratatui (Rust) `insta` snapshots, Charm Bracelet (Go) `teatest` golden files, and Ink (Node) `ink-testing-library`. Use for any TUI where layout regressions otherwise reach users via `screenshot looks wrong in terminal`.

中文简介正在准备中。当前显示原文说明。

testland/qa星标 13(GitHub 13 + cccskills 0)

实测评分 未实测

查看安装方法

包含的文件(2)

  • SKILL.md8.4 KB
  • .tessl-plugin/plugin.json701 B

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

tui-snapshot-tester

Overview

Per textual-testing:

"Snapshot testing is the process of recording the output of a test, and comparing it against the output from previous runs." Textual's pytest-textual-snapshot plugin does this by saving an SVG screenshot of the running app to disk.

A TUI snapshot test:

  1. Renders the TUI to a deterministic frame (SVG / text).
  2. Compares the new frame to a stored baseline.
  3. Fails on diff; produces an HTML diff report so the human reviews the change.
  4. Updates the baseline only when the human says so.

This catches layout regressions (clipped text, wrong column widths, broken borders) that exit-code / output assertions miss.

When to use

  • The unit-under-test is a TUI (Textual / Ratatui / Bubble Tea / Ink / curses).
  • The TUI's value is its visual layout - assertions on individual cells are brittle and miss "the box border now looks broken."
  • The team needs PR-time review of layout changes (vs catching them in user feedback).

For headless CLIs that emit text only, prefer bats-testing + cli-output-conventions; TUI snapshots are only needed for layout-rich UIs.

Step 1 - Install (Python / Textual)

Per txt:

pip install pytest-textual-snapshot

This pulls Textual + the snap_compare pytest fixture.

Step 2 - First snapshot test

Per txt (verbatim):

def test_calculator(snap_compare):
    assert snap_compare("path/to/calculator.py")

First run fails (no baseline). Per txt:

"Only ever run pytest with --snapshot-update if you're happy with how the output looks on the left hand side of the snapshot report."

Workflow:

  1. Run pytest. It fails; emits an HTML report at snapshot_report.html.
  2. Open the report. The "left hand side" shows the new render; the "right hand side" shows the saved baseline.
  3. If the new render is correct, run pytest --snapshot-update to accept it.
  4. Commit the updated __snapshots__/ directory.

Step 3 - Drive interactions before capture

Per txt:

# Press keys before snapshotting
assert snap_compare("path/to/calculator.py", press=["1", "2", "3"])

# Custom terminal dimensions
assert snap_compare("path/to/calculator.py", terminal_size=(50, 100))

# Run setup code (mouse hover, etc.)
async def run_before(pilot) -> None:
    await pilot.hover("#number-5")

assert snap_compare("path/to/calculator.py", run_before=run_before)

The Pilot API per txt:

async def test_keys():
    app = RGBApp()
    async with app.run_test() as pilot:
        await pilot.press("r")
        assert app.screen.styles.background == Color.parse("red")

pilot.press() / pilot.click() / pilot.pause() simulate user input.

Step 4 - CI integration (Textual)

Per txt:

"work well in CI on all supported operating systems, and the snapshot report is just an HTML file which can be exported as a build artifact."

jobs:
  tui-snapshot:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v5
        with: { python-version: '3.13' }
      - run: pip install pytest-textual-snapshot
      - name: Run snapshot tests
        run: pytest tests/ui/
      - uses: actions/upload-artifact@v4
        if: failure()
        with: { name: snapshot-report, path: snapshot_report.html }

Reviewer downloads snapshot_report.html from the failed CI artifact, opens it locally, and decides accept / reject.

Step 5 - Equivalent for Rust / Ratatui

Use insta for snapshot testing:

# Cargo.toml
[dev-dependencies]
insta = "1"
ratatui = { version = "0.29", features = ["test-buffer"] }
#[test]
fn renders_main_view() {
    let mut terminal = Terminal::new(TestBackend::new(80, 24)).unwrap();
    terminal.draw(|f| draw_main(f, &app_state())).unwrap();
    insta::assert_snapshot!(terminal.backend().to_string());
}

Update with cargo insta accept (or cargo insta review for interactive triage). Snapshots stored in tests/snapshots/.

Step 6 - Equivalent for Go / Bubble Tea

Use teatest:

func TestApp(t *testing.T) {
    tm := teatest.NewTestModel(t, NewModel(), teatest.WithInitialTermSize(80, 24))
    tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

    teatest.RequireEqualOutput(t, tm.FinalOutput(t,
        teatest.WithFinalTimeout(2*time.Second)))
}

teatest.RequireEqualOutput writes / compares against testdata/<test-name>.golden. Update with -update:

go test -update ./...

Step 7 - Equivalent for Node / Ink

Use ink-testing-library:

import { render } from 'ink-testing-library';
import App from './app';

test('renders welcome screen', () => {
  const { lastFrame } = render(<App />);
  expect(lastFrame()).toMatchSnapshot();
});

Jest's built-in toMatchSnapshot writes to __snapshots__/. Update with jest -u.

Step 8 - Determinism

Snapshots fail randomly if any of these vary:

  • Date / time in output. Mock the clock (Textual: freezegun; Ratatui: pass now as state; Ink: use vi.useFakeTimers()).
  • Random IDs. Seed PRNGs deterministically.
  • OS-specific glyphs / fonts. Pin OS in CI; warn on cross-OS diffs.
  • Locale. LC_ALL=C in CI.

Without determinism, snapshot tests become noise → team disables.

Step 9 - Snapshot review discipline

Treat snapshot diffs like test diffs in code review:

  • Every snapshot change must be reviewed in PR.
  • The HTML report is the artifact reviewers consult.
  • Auto-update in CI (e.g., bot pushes --snapshot-update commit on diff) defeats the purpose.

The same review discipline applies to browser screenshots (covered by the qa-visual-regression sister plugin).

Anti-patterns

Anti-patternWhy it failsFix
--snapshot-update in CI by defaultDefeats regression detection; baselines drift silently.Updates only on developer machine + reviewed in PR (Step 2).
Snapshots with timestamps / random IDsRandom failures; team disables tests.Mock clock + seed PRNG (Step 8).
One giant snapshot per appAny change forces full baseline review; reviewer skips.Per-screen / per-state snapshots.
Skipping Step 8 (determinism)Cross-OS / cross-machine diffs.LC_ALL=C + pin OS in CI.
No HTML report artifactReviewer can't see the diff; rejects blindly or rubber-stamps.Upload snapshot_report.html artifact (Step 4).

Limitations

  • Brittle to font / terminal width changes. Pin terminal size in tests (Step 3 terminal_size=).
  • Binary diff is harder to review. Per-pixel SVG diffs require the HTML report; raw text diff is unreadable.
  • Slow on large UIs. Each snapshot renders the full UI.
  • Platform divergence. Cross-OS snapshots may diverge by font rendering; restrict CI to one OS for golden files.

References

  • txt - pytest-textual-snapshot, snap_compare, --snapshot-update, Pilot.press / Pilot.click / Pilot.pause, HTML report, CI workflow.
  • insta (Rust): https://insta.rs/.
  • teatest (Go Bubble Tea): https://github.com/charmbracelet/x/tree/main/exp/teatest.
  • ink-testing-library (Node Ink): https://github.com/vadimdemedes/ink-testing-library.
  • bats-testing - exit-code + text output testing (text CLIs); pair with TUI snapshots for layout regression.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Builds a CI gate that fails the build on **new** WCAG / a11y violations introduced by a PR while grandfathering pre-existing violations on a per-rule / per-page baseline. Aggregates verdicts from axe-core / pa11y / Lighthouse a11y / WAVE / IBM Equal Access scans. Use when a project has accumulated a11y debt and a strict "zero violations" gate would block every PR - the ratchet pattern lets the team ship while preventing regressions.

中文简介正在准备中。当前显示原文说明。

testland/qa132026年10月20日 更新

Workflow skill that builds an A/B-test validity checklist from an experiment proposal, walking the canonical design-correctness gates - pre-registered OEC/power/guardrails, randomization unit + SRM check, assignment integrity, telemetry, peeking discipline, novelty/primacy, post-experiment SRM re-check - into a per-experiment checklist + sign-off form. Use when launching, auditing, or governing an experiment. For pitfall mechanics (guardrails, peeking) see experiment-results-interpreter's references; to read an already-valid result use experiment-results-interpreter; for per-SDK harness tests use experiment-sdk-testing - this gates DESIGN, not SDK code.

中文简介正在准备中。当前显示原文说明。

testland/qa132026年10月20日 更新

The single install-flow skill: the reference contract for the PWA install flow (installability gate fields, `beforeinstallprompt` handshake, per-platform paths - Android WebAPK / iOS Share menu / Firefox no-op - and the `display-mode` post-install signal, in references/install-flow-reference.md) plus the build-an-X workflow that emits the Add-to-Home-Screen suite. Walks the four-stage timeline, emitting one test per gate cell per [web.dev/articles/install-criteria][install-criteria], the deferred-prompt → `prompt()` → `userChoice` chain per [web.dev/articles/customize-install][customize-install], the iOS Safari manual-metadata branch (`apple-touch-icon`) per [web.dev/learn/pwa/installation][learn-pwa], and the post-install `(display-mode: standalone)` MQ assertion. Output: a Playwright spec with per-stage cells plus a coverage matrix. Use when a PWA's manifest, icons, or install handler change, when install conversion drops at an unknown stage, or when triaging a flaky install assertion.

中文简介正在准备中。当前显示原文说明。

testland/qa132026年10月20日 更新

Build-an-X workflow that uses an LLM to map existing tests to spec sections - given a spec doc + the test suite, the LLM identifies which tests cover which sections, surfaces uncovered sections (gap), and recommends specific tests to add. Output is a coverage matrix per spec ID. Scope is mapping tests that already exist and naming the gaps, not authoring tests for new acceptance criteria. Use when a spec doc and a test suite both exist but nobody can say which requirements are actually covered - before a release sign-off, an audit, or a decision about where to spend the next round of test effort.

中文简介正在准备中。当前显示原文说明。

testland/qa132026年10月20日 更新

Generates tests from natural-language specs (acceptance criteria, user stories, requirements) using an LLM, with confidence scoring per test case (LLM self-assessment plus heuristics: assertion quality, naming, completeness), batching uncertain cases for human review, and integration with the team's existing test framework. Use when the user asks to generate unit tests from acceptance criteria, convert user stories to test cases, automate test creation from requirements, or augment a spec-driven test suite with AI-generated stubs that are then curated before merge.

中文简介正在准备中。当前显示原文说明。

testland/qa132026年10月20日 更新

Configures Allure Report (test-runner adapter install, `allure-results` directory wiring, `categories.json` for failure classification, `history-trend.json` retention via the copy-history-between-runs pattern), runs the Allure CLI to convert `allure-results` to a static HTML site, and uploads the report as a CI artifact. Use when the team needs richer test reporting than JUnit XML - step-level attachments, per-test history, retry tracking, and severity / epic / feature labeling across framework-agnostic adapters (pytest, Jest, JUnit, TestNG, NUnit, Mocha). As a rich static HTML report generator, it is the open-source alternative to the sunset ExtentReports (JVM/.NET per-test HTML narrative); for hosted cross-run flakiness analytics rather than a static per-run report use currents-integration.

中文简介正在准备中。当前显示原文说明。

testland/qa132026年10月20日 更新

查看 testland 的全部技能

报告此技能的问题