Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ test: ## Run tests

test-verbose: ## Run tests with verbose output
go test -race -count=10 -shuffle on -v -cover ./...

test-trimpath: ## Run tests with -trimpath
GOFLAGS=-trimpath go test -race -count=10 -shuffle on -v -cover ./examples
19 changes: 7 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
- [Running tests on CI](#running-tests-on-ci)
- [No Color](#no-color)
- [Snapshots Structure](#snapshots-structure)
- [Known Limitations](#known-limitations)
- [Acknowledgments](#acknowledgments)
- [Contributing](./contributing.md)
- [Appendix](#appendix)

## Installation

Expand Down Expand Up @@ -411,21 +411,16 @@ map[string]interface{}{
> [!NOTE]
> If your snapshot data contain characters `---` at the start of a line followed by a new line, `go-snaps` will "escape" them and save them as `/-/-/-/` to differentiate them from termination characters.

## Known Limitations

- When running a specific test file by specifying a path `go test ./my_test.go`, `go-snaps` can't track the path so it will mistakenly mark snapshots as obsolete.
- go-snaps doesn't handle CRLF line endings. If you are using Windows, you may need to convert the line endings to LF.
- go-snaps doesn't work when running with `go test -trimpath ./...`. If you want to use `go-snaps` and `trimpath` try passing from env with `GOFLAGS=-trimpath`.

## Acknowledgments

This library used [Jest Snapshoting](https://jestjs.io/docs/snapshot-testing) and [Cupaloy](https://github.com/bradleyjkemp/cupaloy) as inspiration.

- Jest is a full-fledged Javascript testing framework and has robust snapshoting features.
- Cupaloy is a great and simple Golang snapshoting solution.
- The [logo](https://github.com/MariaLetta/free-gophers-pack) was made by [MariaLetta](https://github.com/MariaLetta).

## Appendix

> [!WARNING]
> When running a specific test file by specifying a path `go test ./my_test.go`, `go-snaps` can't track the path so it will mistakenly mark snapshots as obsolete.

> [!IMPORTANT]
> Snapshots should be treated as code. The snapshot artifact should be committed alongside code changes, and reviewed as part of your code review process

> [!NOTE]
> go-snaps doesn't handle CRLF line endings. If you are using Windows, you may need to convert the line endings to LF.
7 changes: 2 additions & 5 deletions examples/matchSnapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"flag"
"fmt"
"os"
"path/filepath"
"runtime"
"testing"

"github.com/gkampitakis/go-snaps/snaps"
Expand Down Expand Up @@ -80,10 +78,9 @@ func TestMatchSnapshot(t *testing.T) {
})

t.Run("should allow absolute path", func(t *testing.T) {
_, b, _, _ := runtime.Caller(0)
basepath := filepath.Dir(b)
dir, _ := os.Getwd()

snaps.WithConfig(snaps.Dir(basepath+"/absolute_path")).
snaps.WithConfig(snaps.Dir(dir+"/absolute_path")).
MatchSnapshot(t, "supporting absolute path")
})

Expand Down
7 changes: 5 additions & 2 deletions snaps/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,12 +318,15 @@ func snapshotPath(c *Config, tName string, isStandalone bool) (string, string) {
callerFilename := baseCaller(3)

dir := c.snapsDir
if !filepath.IsAbs(dir) {
if !filepath.IsAbs(dir) && !isTrimBathBuild {
dir = filepath.Join(filepath.Dir(callerFilename), c.snapsDir)
}

snapPath := filepath.Join(dir, constructFilename(c, callerFilename, tName, isStandalone))
snapPathRel, _ := filepath.Rel(filepath.Dir(callerFilename), snapPath)
snapPathRel := snapPath
if !isTrimBathBuild {
snapPathRel, _ = filepath.Rel(filepath.Dir(callerFilename), snapPath)
}

return snapPath, snapPathRel
}
Expand Down
9 changes: 9 additions & 0 deletions snaps/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"strings"
"sync"

Expand All @@ -22,6 +23,7 @@ var (
defaultConfig = Config{
snapsDir: "__snapshots__",
}
isTrimBathBuild = trimPathBuild()
)

const (
Expand Down Expand Up @@ -138,3 +140,10 @@ func shouldCreate(u *bool) bool {

return true
}

// trimPathBuild checks if the build has trimpath setting true
func trimPathBuild() bool {
goFlags := strings.Split(os.Getenv("GOFLAGS"), " ")

return slices.Contains(goFlags, "-trimpath")
Copy link
Contributor

Choose a reason for hiding this comment

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

Golang accepts both -trimpath and --trimpath - and I know that due to old habits I tend to use -- interactively. Maybe it would be worth checking for both.

Copy link
Owner Author

Choose a reason for hiding this comment

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

ohhhh thanks for pointing this out 🙇 . Btw not sure but I can't find a "good" way to identify if build is trimpath when you run your tests like this

go test -trimpath ./...

if you have any ideas feel free to share them 😄

Copy link
Contributor

Choose a reason for hiding this comment

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

Checking the $GOFLAGS is definitely more of an idea than I could up so far. My best idea was to go rooting around in the golang codebase in the search of the trimpath implementation and taking a look if it produces a side effect that one could measure. So far I figured out that the BuildTrimpath is relevant, but I haven't looked through the occurrences yet: https://github.com/search?q=repo%3Agolang/go%20BuildTrimpath&type=code

Copy link
Contributor

Choose a reason for hiding this comment

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

One thing I did turn up: golang collects information about the build, and among the information recorded is if trimpath was enabled: https://github.com/golang/go/blob/e81f7155154c0f5d40363e84a8f24a5b559b5eed/src/cmd/go/internal/load/pkg.go#L2428

This recorded BuildSetting is then exposed to us with the runtime/debug package.

A trivial test looks like this:

package main

import (
        "runtime/debug"
        "fmt"
)

func main() {
        bi, ok := debug.ReadBuildInfo()
        if ! ok {
                fmt.Println("failed to fetch build info")
                return
        }
        fmt.Println(bi.Settings)
}

The result then is as following:

kandre@W-PF4PY6FH(pts/5) ~/go/src/test % go run main.go                                                                                               
[{-buildmode exe} {-compiler gc} {CGO_ENABLED 1} {CGO_CFLAGS } {CGO_CPPFLAGS } {CGO_CXXFLAGS } {CGO_LDFLAGS } {GOARCH amd64} {GOOS linux} {GOAMD64 v1}]

kandre@W-PF4PY6FH(pts/5) ~/go/src/test % GOFLAGS="" go run main.go
[{-buildmode exe} {-compiler gc} {CGO_ENABLED 1} {CGO_CFLAGS } {CGO_CPPFLAGS } {CGO_CXXFLAGS } {CGO_LDFLAGS } {GOARCH amd64} {GOOS linux} {GOAMD64 v1}]

kandre@W-PF4PY6FH(pts/5) ~/go/src/test % GOFLAGS="-trimpath" go run main.go
[{-buildmode exe} {-compiler gc} {-trimpath true} {CGO_ENABLED 1} {GOARCH amd64} {GOOS linux} {GOAMD64 v1}]

kandre@W-PF4PY6FH(pts/5) ~/go/src/test % go run -trimpath main.go
[{-buildmode exe} {-compiler gc} {-trimpath true} {CGO_ENABLED 1} {GOARCH amd64} {GOOS linux} {GOAMD64 v1}]

Copy link
Owner Author

Choose a reason for hiding this comment

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

I found this but unfortunately this information isn't always captured.

The previous commit on this pr was using the ReadBuildInfo, but when I tried running unit tests with trimpath it was not showing any details which is weird😞
7929c46 (#120)

This is what ReadBuildInfo doc states

// ReadBuildInfo returns the build information embedded
// in the running binary. The information is available only
// in binaries built with module support.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm . I think if build info is present it would than still be the best way to use it, falling back to checking the env var.

I wonder what is causing that - does your go env point at anything specific? I'll have a try when I get some time near a proper PC.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I have updated the function and on my testing

  1. captures all cases, GOFLAGS, flag trimpath either from a main_test or package
  2. don't see any regression on what already exists.

}