Skip to content

refactor(tests): adopt libtest-mimic and custom snapshot_test crate#339

Merged
branchseer merged 7 commits intomainfrom
use-libtest-mimic
Apr 17, 2026
Merged

refactor(tests): adopt libtest-mimic and custom snapshot_test crate#339
branchseer merged 7 commits intomainfrom
use-libtest-mimic

Conversation

@branchseer
Copy link
Copy Markdown
Member

@branchseer branchseer commented Apr 16, 2026

Why

Before this PR, both e2e_snapshots and plan_snapshots used harness = false with a hand-rolled fn main() that:

  • Parsed one positional arg as a substring filter (args().nth(1)), and nothing else — no --list, no --exact, no --ignored, no --test-threads.
  • Iterated fixtures sequentially in a single thread, regardless of machine parallelism.
  • Printed fixture names to stdout as progress, mixed into insta's own stderr diff output, with no structured "passed / failed / filtered out" summary.

Two problems fall out of that:

  • AI-agent friction. Agents (Claude Code, Cursor, etc.) drive tests through cargo test and expect the built-in harness contract: filter a subset with --exact, enumerate with --list, read the standard "N passed; M failed" summary to know what happened. Custom output and missing flags force the agent to grep through ad-hoc progress prints or re-run the full suite just to isolate one fixture. Moving to libtest-mimic removes that friction — the harness behaves exactly like a normal Rust test binary.

  • No parallelism. plan_snapshots in particular is CPU-bound and embarrassingly parallel per fixture, but the old harness ran it single-threaded. libtest-mimic runs fixtures in parallel by default (via available_parallelism()), using the hardware the CI already pays for. (E2E tests spawn PTY children and send signals; on Linux we pin them back to single-threaded — see the "Platform-specific fixes" section below.)

Summary

Two-part migration of the e2e and plan snapshot test harnesses:

1. Adopt libtest-mimic for proper cargo test integration

Migrating to libtest-mimic gives:

  • Proper cargo test flag support: --filter, --list, --exact, --ignored, --test-threads
  • Standard test runner output formatting (running N tests / test X ... ok / test result: ok. ... passed; ... failed)
  • Parallel fixture execution by default

2. Replace insta with a custom snapshot_test crate

Created crates/snapshot_test with two methods that return Result<(), String> — containing a unified diff — so failures integrate cleanly with libtest-mimic::Failed:

  • check_snapshot(name, actual) — compares raw text
  • check_json_snapshot(name, comment, value) — serializes to pretty JSON, prepends // {comment} header, writes to .jsonc

Key behaviors:

  • Drops the insta dependency and its transitive deps
  • Unified diff appears directly in the failures: section of test output (see crates/snapshot_test/README.md for why insta didn't fit)
  • Plan JSON snapshots now use .jsonc extension with // run ... command headers (e.g. // run build --recursive); e2e snapshots keep .snap
  • Existing insta YAML headers stripped from all 310 snapshot files
  • UPDATE_SNAPSHOTS=1 env var accepts new output in-place (replaces INSTA_UPDATE)
  • Snapshot directories excluded from oxfmt via .oxfmtrc.json to prevent trailing-comma insertion in .jsonc files

Platform-specific fixes

  • Windows: CRLF line endings are normalized to LF when reading snapshot files
  • Linux: e2e tests forced to single-threaded (test_threads = 1), matching the pre-PR custom-harness behavior. libtest-mimic defaults to available_parallelism(), which caused PTY/signal-routing races in the ctrl-c test. macOS and Windows keep parallel execution.

Test plan

  • cargo test -p vite_task_plan --test plan_snapshots — 45 tests pass
  • cargo test -p vite_task_bin --test e2e_snapshots — 36 tests pass
  • cargo test -- --list lists all fixture names
  • cargo test -- --exact <name> filters correctly
  • Tampered .snap/.jsonc file produces a unified diff in the failure message, pointing to the .snap.new / .jsonc.new file
  • UPDATE_SNAPSHOTS=1 accepts new output in-place and clears .new files
  • CI stability: 5 consecutive green runs across Linux, macOS (arm64 + x86_64), Windows, and musl

🤖 Generated with Claude Code

branchseer and others added 2 commits April 16, 2026 21:58
…nesses

Replace ad-hoc argument parsing with libtest-mimic to get proper cargo test
integration (--filter, --list, --exact, formatted output).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create `crates/snapshot_test` with `check_snapshot` and
  `check_json_snapshot` that return `Result<(), String>` with unified
  diffs, integrating cleanly with libtest-mimic's `Failed` type.
- Drop `insta` dependency and all its transitive deps.
- Plan JSON snapshots use `.jsonc` extension with `// vp run ...`
  comment headers; e2e snapshots keep `.snap`.
- Strip insta YAML headers from all existing snapshot files.
- Exclude snapshot directories from oxfmt to prevent trailing comma
  insertion in `.jsonc` files.
- Support `UPDATE_SNAPSHOTS=1` to accept new output in-place.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe0e4a11c3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/snapshot_test/src/lib.rs
branchseer and others added 3 commits April 16, 2026 23:31
- Normalize \r\n to \n when reading snapshot files for Windows compat
- Replace redundant closures with Into::into
- Remove unfulfilled #[expect] attributes
- Add disallowed_methods to snapshot_test module-level expect

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
libtest-mimic defaults to `available_parallelism()` threads, but the
previous custom `fn main()` harness ran fixtures sequentially. Running
e2e fixtures in parallel causes PTY and signal-routing contention,
especially on the ctrl-c test, which intermittently fails on Linux/musl
CI when task B gets launched before vt processes the ctrl-c signal.

Force `test_threads = 1` unless the user explicitly overrides via
`--test-threads`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
macOS and Windows CI were unaffected by the ctrl-c flakiness. Scope
the single-thread override to Linux only so other platforms keep the
faster parallel execution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@branchseer branchseer changed the title refactor(tests): replace insta with custom snapshot_test crate refactor(tests): adopt libtest-mimic and custom snapshot_test crate Apr 17, 2026
branchseer and others added 2 commits April 17, 2026 08:33
Explain why we didn't use `insta`: its panic-based assertion API
prints the diff to stderr, which doesn't make it into
libtest-mimic's failure summary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace stale `INSTA_UPDATE=always` references with `UPDATE_SNAPSHOTS=1`
in CLAUDE.md and CONTRIBUTING.md to match the new snapshot_test crate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@branchseer
Copy link
Copy Markdown
Member Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 775c31b255

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/snapshot_test/src/lib.rs
value: &impl Serialize,
) -> Result<(), String> {
let json = serde_json::to_string_pretty(value).expect("failed to serialize snapshot value");
self.check_snapshot(&format!("{name}.jsonc"), &format!("// {comment}\n{json}\n"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Avoid generating unignored .jsonc.new artifacts

JSON snapshot assertions now produce {name}.jsonc.new on failure, but the repository ignore rule only covers *.snap.new. That means a normal failing plan snapshot run leaves untracked .jsonc.new files in the worktree that are easy to accidentally commit, adding noise and friction to snapshot workflows.

Useful? React with 👍 / 👎.

@branchseer branchseer merged commit 26baabe into main Apr 17, 2026
9 checks passed
@branchseer branchseer deleted the use-libtest-mimic branch April 17, 2026 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant