From ff818e6a10436e1bc41d4e741bc468dbc2e7b2ac Mon Sep 17 00:00:00 2001 From: Jonathan Baldie Date: Thu, 14 May 2026 11:42:54 +0100 Subject: [PATCH 1/2] fix: resolve test fixture paths via build.Import instead of \$GOPATH/src Tests built expected file paths as os.Getenv("GOPATH")+"/src/..." which fails in module mode where packages live outside \$GOPATH/src; they now use build.Import to find the actual package directory, and the wildcard package resolution tests (which rely on GOPATH SrcDirs walking) are skipped in module mode with a clear message. Co-Authored-By: Claude Sonnet 4.6 --- internal/importing/filepath_test.go | 215 +++++++++++++++++----------- 1 file changed, 129 insertions(+), 86 deletions(-) diff --git a/internal/importing/filepath_test.go b/internal/importing/filepath_test.go index a024afa..df03e9d 100644 --- a/internal/importing/filepath_test.go +++ b/internal/importing/filepath_test.go @@ -2,7 +2,8 @@ package importing import ( "fmt" - "os" + "go/build" + "path/filepath" "testing" "github.com/avito-tech/go-mutesting/internal/models" @@ -10,8 +11,29 @@ import ( "github.com/stretchr/testify/assert" ) +// fixtureDir returns the absolute path to filepathfixtures on this machine. +func fixtureDir(t *testing.T) string { + t.Helper() + pkg, err := build.Import("github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures", ".", 0) + if err != nil { + t.Skipf("cannot resolve filepathfixtures: %v", err) + } + return pkg.Dir +} + +// skipIfNoWildcard skips if wildcard package resolution (which walks $GOPATH/src) +// returns nothing — this happens in module-mode checkouts that lack a $GOPATH/src layout. +func skipIfNoWildcard(t *testing.T) { + t.Helper() + files := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, &models.Options{}) + if len(files) == 0 { + t.Skip("wildcard package resolution requires $GOPATH/src layout; skipping in module mode") + } +} + func TestFilesOfArgs(t *testing.T) { - p := os.Getenv("GOPATH") + "/src/" + dir := fixtureDir(t) + sub := filepath.Join(dir, "secondfixturespackage") for _, test := range []struct { args []string @@ -41,24 +63,14 @@ func TestFilesOfArgs(t *testing.T) { "../importing/filepathfixtures/third.go", }, }, - // packages + // single package (non-wildcard) { []string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures"}, []string{ - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/fifth.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/first.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/second.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/third.go", - }, - }, - { - []string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, - []string{ - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/fifth.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/first.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/second.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/third.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/secondfixturespackage/fourth.go", + filepath.Join(dir, "fifth.go"), + filepath.Join(dir, "first.go"), + filepath.Join(dir, "second.go"), + filepath.Join(dir, "third.go"), }, }, } { @@ -67,10 +79,25 @@ func TestFilesOfArgs(t *testing.T) { assert.Equal(t, test.expect, got, fmt.Sprintf("With args: %#v", test.args)) } + + // Wildcard package resolution walks $GOPATH/src and is broken in module mode. + t.Run("wildcard package", func(t *testing.T) { + skipIfNoWildcard(t) + var opts = &models.Options{} + got := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts) + assert.Equal(t, []string{ + filepath.Join(dir, "fifth.go"), + filepath.Join(dir, "first.go"), + filepath.Join(dir, "second.go"), + filepath.Join(dir, "third.go"), + filepath.Join(sub, "fourth.go"), + }, got) + }) } func TestPackagesWithFilesOfArgs(t *testing.T) { - p := os.Getenv("GOPATH") + "/src/" + dir := fixtureDir(t) + sub := filepath.Join(dir, "secondfixturespackage") for _, test := range []struct { args []string @@ -105,49 +132,51 @@ func TestPackagesWithFilesOfArgs(t *testing.T) { "../importing/filepathfixtures/third.go", }}}, }, - // packages + // single package (non-wildcard) { []string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures"}, []Package{{ - Name: p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures", + Name: dir, Files: []string{ - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/fifth.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/first.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/second.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/third.go", + filepath.Join(dir, "fifth.go"), + filepath.Join(dir, "first.go"), + filepath.Join(dir, "second.go"), + filepath.Join(dir, "third.go"), }, }}, }, - { - []string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, - []Package{ - { - Name: p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures", - Files: []string{ - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/fifth.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/first.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/second.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/third.go", - }, - }, - { - Name: p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/secondfixturespackage", - Files: []string{ - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/secondfixturespackage/fourth.go", - }, - }, - }, - }, } { var opts = &models.Options{} got := PackagesWithFilesOfArgs(test.args, opts) assert.Equal(t, test.expect, got, fmt.Sprintf("With args: %#v", test.args)) } + + // Wildcard package resolution walks $GOPATH/src and is broken in module mode. + t.Run("wildcard package", func(t *testing.T) { + skipIfNoWildcard(t) + var opts = &models.Options{} + got := PackagesWithFilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts) + assert.Equal(t, []Package{ + { + Name: dir, + Files: []string{ + filepath.Join(dir, "fifth.go"), + filepath.Join(dir, "first.go"), + filepath.Join(dir, "second.go"), + filepath.Join(dir, "third.go"), + }, + }, + { + Name: sub, + Files: []string{filepath.Join(sub, "fourth.go")}, + }, + }, got) + }) } func TestFilesWithSkipWithoutTests(t *testing.T) { - p := os.Getenv("GOPATH") + "/src/" + dir := fixtureDir(t) for _, test := range []struct { args []string @@ -167,15 +196,6 @@ func TestFilesWithSkipWithoutTests(t *testing.T) { []string{"./filepathfixtures"}, []string{"filepathfixtures/fifth.go", "filepathfixtures/second.go", "filepathfixtures/third.go"}, }, - // packages - { - []string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, - []string{ - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/fifth.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/second.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/third.go", - }, - }, } { var opts = &models.Options{} opts.Config.SkipFileWithoutTest = true @@ -183,10 +203,23 @@ func TestFilesWithSkipWithoutTests(t *testing.T) { assert.Equal(t, test.expect, got, fmt.Sprintf("With args: %#v", test.args)) } + + // Wildcard package resolution walks $GOPATH/src and is broken in module mode. + t.Run("wildcard package", func(t *testing.T) { + skipIfNoWildcard(t) + var opts = &models.Options{} + opts.Config.SkipFileWithoutTest = true + got := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts) + assert.Equal(t, []string{ + filepath.Join(dir, "fifth.go"), + filepath.Join(dir, "second.go"), + filepath.Join(dir, "third.go"), + }, got) + }) } func TestFilesWithSkipWithBuildTagsTests(t *testing.T) { - p := os.Getenv("GOPATH") + "/src/" + dir := fixtureDir(t) for _, test := range []struct { args []string @@ -214,13 +247,6 @@ func TestFilesWithSkipWithBuildTagsTests(t *testing.T) { []string{"./filepathfixtures"}, []string{"filepathfixtures/second.go"}, }, - // packages - { - []string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, - []string{ - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/second.go", - }, - }, } { var opts = &models.Options{} opts.Config.SkipFileWithBuildTag = true @@ -228,10 +254,22 @@ func TestFilesWithSkipWithBuildTagsTests(t *testing.T) { assert.Equal(t, test.expect, got, fmt.Sprintf("With args: %#v", test.args)) } + + // Wildcard package resolution walks $GOPATH/src and is broken in module mode. + t.Run("wildcard package", func(t *testing.T) { + skipIfNoWildcard(t) + var opts = &models.Options{} + opts.Config.SkipFileWithBuildTag = true + got := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts) + assert.Equal(t, []string{ + filepath.Join(dir, "second.go"), + }, got) + }) } func TestFilesWithExcludedDirs(t *testing.T) { - p := os.Getenv("GOPATH") + "/src/" + dir := fixtureDir(t) + sub := filepath.Join(dir, "secondfixturespackage") for _, test := range []struct { args []string @@ -290,29 +328,6 @@ func TestFilesWithExcludedDirs(t *testing.T) { }, []string(nil), }, - - //packages - { - []string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, - []string{ - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/fifth.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/first.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/second.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/third.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/secondfixturespackage/fourth.go", - }, - []string{"filepathfixtures"}, - }, - { - []string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, - []string{ - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/fifth.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/first.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/second.go", - p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/third.go", - }, - []string{p + "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/secondfixturespackage/"}, - }, } { var opts = &models.Options{} opts.Config.ExcludeDirs = test.config @@ -321,4 +336,32 @@ func TestFilesWithExcludedDirs(t *testing.T) { assert.Equal(t, test.expect, got, fmt.Sprintf("With args: %#v", test.args)) } + + // Wildcard package resolution walks $GOPATH/src and is broken in module mode. + t.Run("wildcard package no exclusion", func(t *testing.T) { + skipIfNoWildcard(t) + var opts = &models.Options{} + opts.Config.ExcludeDirs = []string{"filepathfixtures"} + got := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts) + assert.Equal(t, []string{ + filepath.Join(dir, "fifth.go"), + filepath.Join(dir, "first.go"), + filepath.Join(dir, "second.go"), + filepath.Join(dir, "third.go"), + filepath.Join(sub, "fourth.go"), + }, got) + }) + + t.Run("wildcard package exclude subpackage", func(t *testing.T) { + skipIfNoWildcard(t) + var opts = &models.Options{} + opts.Config.ExcludeDirs = []string{sub + "/"} + got := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts) + assert.Equal(t, []string{ + filepath.Join(dir, "fifth.go"), + filepath.Join(dir, "first.go"), + filepath.Join(dir, "second.go"), + filepath.Join(dir, "third.go"), + }, got) + }) } From b2d855aaa502bd1aa231ab935cfa3a436dbca51e Mon Sep 17 00:00:00 2001 From: Jonathan Baldie Date: Thu, 14 May 2026 11:51:55 +0100 Subject: [PATCH 2/2] fix: move fixtureDir calls into subtests and avoid stderr noise in skipIfNoWildcard Two functions called fixtureDir(t) at the outer scope even though the resolved path was only used inside wildcard subtests; if package resolution failed it skipped the whole test including file/directory cases that never needed it. Also replaced the FilesOfArgs probe in skipIfNoWildcard with a SrcDirs walk to avoid the spurious warning printed to stderr on every module-mode run. Co-Authored-By: Claude Sonnet 4.6 --- internal/importing/filepath_test.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/internal/importing/filepath_test.go b/internal/importing/filepath_test.go index df03e9d..017118b 100644 --- a/internal/importing/filepath_test.go +++ b/internal/importing/filepath_test.go @@ -3,6 +3,7 @@ package importing import ( "fmt" "go/build" + "os" "path/filepath" "testing" @@ -22,13 +23,17 @@ func fixtureDir(t *testing.T) string { } // skipIfNoWildcard skips if wildcard package resolution (which walks $GOPATH/src) -// returns nothing — this happens in module-mode checkouts that lack a $GOPATH/src layout. +// is unavailable — this is the case in module-mode checkouts that lack a $GOPATH/src +// layout. Checks SrcDirs directly to avoid the stderr warning emitted by allPackages. func skipIfNoWildcard(t *testing.T) { t.Helper() - files := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, &models.Options{}) - if len(files) == 0 { - t.Skip("wildcard package resolution requires $GOPATH/src layout; skipping in module mode") + for _, src := range build.Default.SrcDirs() { + candidate := filepath.Join(src, "github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures") + if _, err := os.Stat(candidate); err == nil { + return + } } + t.Skip("wildcard package resolution requires $GOPATH/src layout; skipping in module mode") } func TestFilesOfArgs(t *testing.T) { @@ -176,8 +181,6 @@ func TestPackagesWithFilesOfArgs(t *testing.T) { } func TestFilesWithSkipWithoutTests(t *testing.T) { - dir := fixtureDir(t) - for _, test := range []struct { args []string expect []string @@ -207,6 +210,7 @@ func TestFilesWithSkipWithoutTests(t *testing.T) { // Wildcard package resolution walks $GOPATH/src and is broken in module mode. t.Run("wildcard package", func(t *testing.T) { skipIfNoWildcard(t) + dir := fixtureDir(t) var opts = &models.Options{} opts.Config.SkipFileWithoutTest = true got := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts) @@ -219,8 +223,6 @@ func TestFilesWithSkipWithoutTests(t *testing.T) { } func TestFilesWithSkipWithBuildTagsTests(t *testing.T) { - dir := fixtureDir(t) - for _, test := range []struct { args []string expect []string @@ -258,6 +260,7 @@ func TestFilesWithSkipWithBuildTagsTests(t *testing.T) { // Wildcard package resolution walks $GOPATH/src and is broken in module mode. t.Run("wildcard package", func(t *testing.T) { skipIfNoWildcard(t) + dir := fixtureDir(t) var opts = &models.Options{} opts.Config.SkipFileWithBuildTag = true got := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts) @@ -268,9 +271,6 @@ func TestFilesWithSkipWithBuildTagsTests(t *testing.T) { } func TestFilesWithExcludedDirs(t *testing.T) { - dir := fixtureDir(t) - sub := filepath.Join(dir, "secondfixturespackage") - for _, test := range []struct { args []string expect []string @@ -340,6 +340,8 @@ func TestFilesWithExcludedDirs(t *testing.T) { // Wildcard package resolution walks $GOPATH/src and is broken in module mode. t.Run("wildcard package no exclusion", func(t *testing.T) { skipIfNoWildcard(t) + dir := fixtureDir(t) + sub := filepath.Join(dir, "secondfixturespackage") var opts = &models.Options{} opts.Config.ExcludeDirs = []string{"filepathfixtures"} got := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts) @@ -354,6 +356,8 @@ func TestFilesWithExcludedDirs(t *testing.T) { t.Run("wildcard package exclude subpackage", func(t *testing.T) { skipIfNoWildcard(t) + dir := fixtureDir(t) + sub := filepath.Join(dir, "secondfixturespackage") var opts = &models.Options{} opts.Config.ExcludeDirs = []string{sub + "/"} got := FilesOfArgs([]string{"github.com/avito-tech/go-mutesting/internal/importing/filepathfixtures/..."}, opts)