A birdie and insta inspired snapshot testing library for Go.
go get github.com/ptdewey/shutterThe review TUI is included in the module and can be installed as a standalone executable:
# executable is installed as `shutter`
go install github.com/ptdewey/shutter/cmd/shutter@latestpackage package_test
funcTestSomething(t*testing.T) {
result:=SomeFunction("foo")
shutter.Snap(t, "test title", result)
}Use SnapMany() when you need to snapshot multiple related values together:
funcTestMultipleValues(t*testing.T) {
request:=buildRequest()
response:=handleRequest(request)
// Snapshot both request and response togethershutter.SnapMany(t, "title", []any{request, response})
}shutter supports data scrubbing and field filtering to handle dynamic or sensitive data in snapshots.
Scrubbers transform content before snapshotting, typically to replace dynamic or sensitive data with placeholders:
funcTestUserAPI(t*testing.T) {
user:=api.GetUser("123")
// Replace UUIDs and timestamps with placeholdersshutter.Snap(t, "user", user,
shutter.ScrubUUID(),
shutter.ScrubTimestamp(),
)
}Built-in Scrubbers:
ScrubUUID()- Replaces UUIDs with<UUID>ScrubTimestamp()- Replaces ISO8601 timestamps with<TIMESTAMP>ScrubEmail()- Replaces email addresses with<EMAIL>ScrubIP()- Replaces IPv4 addresses with<IP>ScrubJWT()- Replaces JWT tokens with<JWT>ScrubCreditCard()- Replaces credit card numbers with<CREDIT_CARD>ScrubAPIKey()- Replaces API keys with<API_KEY>ScrubDate()- Replaces various date formats with<DATE>ScrubUnixTimestamp()- Replaces Unix timestamps with<UNIX_TS>
Custom Scrubbers:
// Using regex patternsshutter.ScrubRegex(`user-\d+`, "<USER_ID>")
// Using exact string matchingshutter.ScrubExact("secret_value", "<REDACTED>")
// Using custom functionsshutter.ScrubWith(func(contentstring) string {
returnstrings.ReplaceAll(content, "localhost", "<HOST>")
})Ignore patterns remove specific fields from JSON structures before snapshotting:
funcTestAPIResponse(t*testing.T) {
response:=api.GetData()
jsonBytes, _:=json.Marshal(response)
// Ignore sensitive fields and null valuesshutter.SnapJSON(t, "response", string(jsonBytes),
shutter.IgnoreSensitive(),
shutter.IgnoreNull(),
shutter.IgnoreKey("created_at", "updated_at"),
)
}Built-in Ignore Patterns:
IgnoreSensitive()- Ignores common sensitive keys (password, token, api_key, etc.)IgnoreEmpty()- Ignores fields with empty string valuesIgnoreNull()- Ignores fields with null values
Custom Ignore Patterns:
// Ignore specific keysshutter.IgnoreKey("id", "timestamp", "version")
// Ignore key-value pairsshutter.IgnoreKeyValue("status", "pending")
// Ignore keys matching a regex patternshutter.IgnoreKeyMatching(`^_.*`) // Ignore all keys starting with underscore// Ignore specific valuesshutter.IgnoreValue("null", "undefined", "")
// Using custom functionsshutter.IgnoreWith(func(key, valuestring) bool {
returnstrings.HasPrefix(key, "temp_")
})You can combine multiple scrubbers and ignore patterns:
funcTestComplexData(t*testing.T) {
data:=generateTestData()
jsonBytes, _:=json.Marshal(data)
shutter.SnapJSON(t, "data", string(jsonBytes),
// First, remove unwanted fieldsshutter.IgnoreSensitive(),
shutter.IgnoreKey("debug_info"),
shutter.IgnoreNull(),
// Then, scrub dynamic values in remaining fieldsshutter.ScrubUUID(),
shutter.ScrubTimestamp(),
shutter.ScrubEmail(),
)
}Note: Ignore patterns only work with SnapJSON(). Use scrubbers with Snap(), SnapMany(), or SnapString().
Snapshot Functions:
// For single values (structs, maps, slices, etc.)shutter.Snap(t, "title", value, options...)
// For multiple related valuesshutter.SnapMany(t, "title", []any{value1, value2, value3}, options...)
// For JSON strings (supports both scrubbers and ignore patterns)shutter.SnapJSON(t, "title", jsonString, options...)
// For plain stringsshutter.SnapString(t, "title", content, options...)To review a set of snapshots, run (CLI version -- not recommended):
go run github.com/ptdewey/shutter/cmd/cli reviewShutter can also be used programmatically:
// Example: tools/shutter/main.gopackage main
import"github.com/ptdewey/shutter"funcmain() {
// This will start the CLI review toolshutter.Review()
}Which can then be run with:
go run tools/shutter/main.goShutter also includes (in a separate Go module) a Bubbletea TUI in cmd/tui/main.go. (The TUI is shipped in a separate module to make the added dependencies optional)
After installing the TUI:
shuttera- Accept current snapshotr- Reject current snapshots- Skip current snapshotA- Accept all remaining snapshotsR- Reject all remaining snapshotsS- Skip all remaining snapshotsq- Quit
# Accept all new snapshots without review
shutter accept-all
# Reject all new snapshots without review
shutter reject-all