Add in-house snapshot testing and convert output assertions to snapshots - #443
Open
skyrpex wants to merge 23 commits into
Open
Add in-house snapshot testing and convert output assertions to snapshots#443skyrpex wants to merge 23 commits into
skyrpex wants to merge 23 commits into
Conversation
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
skyrpex
force-pushed
the
claude/go-testing-tools-11f5d0
branch
from
August 11, 2026 12:43
cd92645 to
f3cd58b
Compare
Co-authored-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Re-applies the testify-to-must migration and snapshot conversions on top of the Windows PTY/fake-tool test rework from #444. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…utput Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts: # test/integration/logout_test.go # test/integration/logs_test.go # test/integration/status_test.go
skyrpex
marked this pull request as ready for review
August 12, 2026 15:18
There was a problem hiding this comment.
In-house file-snapshot helper plus a mass Contains→snapshot conversion; careful, well-documented, and it caught two real bugs along the way — I ran the non-Docker packages (internal/snap, internal/output, internal/extension) locally and they pass.
- suggestion(non-blocking): on
test/integration/json_envelope_test.go— the conversion replaces named assertions (assert.Equal("NOT_JSON_CAPABLE", ...)) with full-envelopeMatchJSON. I confirmed the.snapfiles pincode/category/status/schemaVersion, so this is strictly stronger for the agent-facing contract; the only cost is the failure surface shifting from a named expectation to a diff. This is exactly the kept-vs-converted judgment your Review note asks a human to double-check. - thought(non-blocking): on
test/integration/snap_sanitize_test.go— a few masks are shape-anchored across the whole stream (sanitizeSizeRe, andsanitizeGatewayHostRemasking any host on:4566). Correct today since those values are environment-dependent, but if a test ever needs to assert a specific size or endpoint host on:4566it would be silently masked — worth a comment or a narrower anchor if that case appears. - praise: the env hardening + defense-in-depth
AUTH_TOKEN=redaction, and the two bugs the conversion surfaced (the token leaking into public CI artifacts and the Windows phantomextensionsextension ininternal/extension/resolve.go, now correctly gated on PATHEXT to match dispatch) are a strong argument for the whole exercise.
Automated review on behalf of @gtsiolis.
Generated by Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Re-review of the delta since my last pass — a main merge brought in the new extension MACHINE_ID field and be4fbca masks it in the snapshots, so my earlier shape-anchored-mask thought is now addressed inline.
- praise: on
test/integration/snap_sanitize_test.go— theMACHINE_IDmask correctly folds into the existing(?:SESSION|MACHINE)_ID=anchor and documents why the value is environment-dependent (origin prefix + host hash); I confirmed via the API that everyMACHINE_ID=line in the committed snapshots renders as<id>, so cross-host/CI determinism holds.
Automated review on behalf of @gtsiolis.
Generated by Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Exploration of modern Go testing tooling for more readable tests: many integration tests pinned CLI output shape through long
Contains/NotContainschains that are hard to read, easy to under-assert, and painful to update.Solution
internal/snap: in-house file-snapshot helper, no new dependencies. One archive per test file (__snapshots__/<test_file>.snap) in a plain bracket-header format: a[TestName_N]header perMatchcall, the value verbatim, a---terminator line, blank-line separated. The format has no escaping, so a value containing a bare---line is rejected (round-trip guard, covered by tests).Matchfor text,MatchJSONwith dotted-path masking (<any>) for JSON envelopes,Cleanfor obsolete-entry/orphan-archive detection viaTestMain. Missing snapshots are created locally but fail in CI;UPDATE_SNAPS=true go testrewrites.require-for-preconditions /assert-for-expectations split (an in-housemustpackage was trialed mid-PR and reverted).internal/output): everyContains/NotContainschain on CLI output whose full stream is deterministic across runs and platforms is now a snapshot. Streams are always snapshotted separately (oneMatchper stream, neverstdout+stderrconcatenated). Deliberately left asContains: Docker-backed tests (volatile pull/timing output), streams embedding temp paths or host-dependent text (runtime-detection hints, platform dial errors), PTY/Bubble Tea transcripts, and platform-gated tests whose snapshots can't be generated cross-platform.AWS_PROFILE,AWS_REGION, real-looking keys, endpoint overrides) showed ambient AWS env leaking into wrapped-tool env dumps and snapshotted output. Thetest/integration/envbase constructors now strip ambientAWS_*credential/region/profile vars plusAWS_ENDPOINT_URL/LSTK_ENDPOINT_URL(same spirit as the existing never-inherit-real-$HOMErule); tests exercising ambient behavior set them explicitly, which still wins.lstk-extensions.tomllisted as a phantomextensionsextension in--helpon Windows (fixed ininternal/extension/resolve.go— listing now honors PATHEXT like dispatch already did); a CI failure diff leaked the real auth token into public artifacts (fixed by stripping ambient tokens in test envs + sanitizer redaction; label-anchored sanitizer masks ports, hosts, versions, dates, sizes)..gitattributes:*.snap -textso Windows checkouts can't CRLF-mangle archives.Docs
Docs impact
Nothing user-facing to document: test infrastructure and test-only changes. Contributor-facing usage (
snap.Match,UPDATE_SNAPS, sanitization rules, per-stream convention) is documented in CLAUDE.md's Testing section.Review
Human review advisable: this introduces shared test infrastructure (
internal/snap) and a repo-wide testing convention, and the mass conversion intentionally deletesNotContainschecks wherever a full-stream snapshot subsumes them — worth a second pair of eyes on the kept-vs-converted judgment calls. All 176 snapshot-backed tests pass (also under a deliberately polluted AWS environment), unit tests and lint are green on both modules.Co-Authored-By: Claude noreply@anthropic.com
🤖 Generated with Claude Code