From f1d45eb2868cb7c930fa4ab9b22b5a905afa0b5f Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 28 Oct 2025 00:24:43 +0300 Subject: [PATCH 1/3] feat(gomod): add GetFullImportPath utility and comprehensive tests Implement GetFullImportPath to resolve full Go import paths, with helper functions findGoMod and parseModulePath. Add example usage in internal/gomod/example_test.go and extensive unit tests covering various scenarios and edge cases. Include testdata for simple and nested modules. --- internal/gomod/example_test.go | 41 ++++ internal/gomod/gomod.go | 106 +++++++++ internal/gomod/gomod_test.go | 202 ++++++++++++++++++ internal/gomod/testdata/nested_module/go.mod | 3 + internal/gomod/testdata/nested_module/lib.go | 5 + internal/gomod/testdata/no_module/orphan.go | 3 + internal/gomod/testdata/simple_module/go.mod | 3 + internal/gomod/testdata/simple_module/main.go | 7 + .../gomod/testdata/simple_module/pkg/utils.go | 7 + 9 files changed, 377 insertions(+) create mode 100644 internal/gomod/example_test.go create mode 100644 internal/gomod/gomod.go create mode 100644 internal/gomod/gomod_test.go create mode 100644 internal/gomod/testdata/nested_module/go.mod create mode 100644 internal/gomod/testdata/nested_module/lib.go create mode 100644 internal/gomod/testdata/no_module/orphan.go create mode 100644 internal/gomod/testdata/simple_module/go.mod create mode 100644 internal/gomod/testdata/simple_module/main.go create mode 100644 internal/gomod/testdata/simple_module/pkg/utils.go diff --git a/internal/gomod/example_test.go b/internal/gomod/example_test.go new file mode 100644 index 0000000..f799c4b --- /dev/null +++ b/internal/gomod/example_test.go @@ -0,0 +1,41 @@ +package gomod_test + +import ( + "fmt" + "log" + + "github.com/cweill/gotests/internal/gomod" +) + +func ExampleGetFullImportPath_file() { + // Get import path for a specific Go file + importPath, err := gomod.GetFullImportPath("gomod.go") + if err != nil { + log.Fatal(err) + } + + fmt.Println(importPath) + // Output: github.com/cweill/gotests/internal/gomod +} + +func ExampleGetFullImportPath_directory() { + // Get import path for a package directory + importPath, err := gomod.GetFullImportPath(".") + if err != nil { + log.Fatal(err) + } + + fmt.Println(importPath) + // Output: github.com/cweill/gotests/internal/gomod +} + +func ExampleGetFullImportPath_moduleRoot() { + // Get import path for the module root directory + importPath, err := gomod.GetFullImportPath("../..") + if err != nil { + log.Fatal(err) + } + + fmt.Println(importPath) + // Output: github.com/cweill/gotests +} diff --git a/internal/gomod/gomod.go b/internal/gomod/gomod.go new file mode 100644 index 0000000..44d7d30 --- /dev/null +++ b/internal/gomod/gomod.go @@ -0,0 +1,106 @@ +package gomod + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strings" +) + +// GetFullImportPath resolves the full Go import path for any file or directory +// within a Go module. Returns the complete import path like "github.com/user/repo/pkg". +// +// startAt can be either: +// - A Go source file path (e.g., "/path/to/project/main.go") +// - A directory path (e.g., "/path/to/project/pkg") +// - An absolute or relative path +// +// Returns an error if: +// - No go.mod found in the directory tree +// - go.mod is malformed or missing module directive +// - Path resolution fails +func GetFullImportPath(startAt string) (string, error) { + absPath, err := filepath.Abs(startAt) + if err != nil { + return "", fmt.Errorf("failed to get absolute path for %s: %w", startAt, err) + } + + // If it's a file, get its directory + if info, err := os.Stat(absPath); err == nil && !info.IsDir() { + absPath = filepath.Dir(absPath) + } + + modRoot, err := findGoMod(absPath) + if err != nil { + return "", err + } + + modulePath, err := parseModulePath(modRoot) + if err != nil { + return "", err + } + + relPath, err := filepath.Rel(modRoot, absPath) + if err != nil { + return "", fmt.Errorf("failed to calculate relative path from %s to %s: %w", modRoot, absPath, err) + } + + if relPath == "." { + return modulePath, nil + } + + return filepath.Join(modulePath, relPath), nil +} + +// findGoMod walks up the directory tree from startDir to find a go.mod file. +// Returns the directory containing go.mod, or an error if not found. +func findGoMod(startDir string) (string, error) { + current := startDir + + for { + modPath := filepath.Join(current, "go.mod") + if _, err := os.Stat(modPath); err == nil { + return current, nil + } + + parent := filepath.Dir(current) + if parent == current { + // Reached root directory + break + } + current = parent + } + + return "", fmt.Errorf("go.mod not found in %s or any parent directory", startDir) +} + +// parseModulePath reads the go.mod file in modRoot and extracts the module path. +// Returns the module path or an error if parsing fails. +func parseModulePath(modRoot string) (string, error) { + modFile := filepath.Join(modRoot, "go.mod") + + file, err := os.Open(modFile) + if err != nil { + return "", fmt.Errorf("failed to open go.mod at %s: %w", modFile, err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if strings.HasPrefix(line, "module ") { + modulePath := strings.TrimSpace(line[7:]) // Remove "module " prefix + if modulePath == "" { + return "", fmt.Errorf("empty module path in %s", modFile) + } + return modulePath, nil + } + } + + if err := scanner.Err(); err != nil { + return "", fmt.Errorf("error reading go.mod at %s: %w", modFile, err) + } + + return "", fmt.Errorf("module directive not found in %s", modFile) +} diff --git a/internal/gomod/gomod_test.go b/internal/gomod/gomod_test.go new file mode 100644 index 0000000..358daab --- /dev/null +++ b/internal/gomod/gomod_test.go @@ -0,0 +1,202 @@ +package gomod + +import ( + "path/filepath" + "testing" +) + +func TestGetFullImportPath(t *testing.T) { + tests := []struct { + name string + startAt string + expected string + hasError bool + }{ + { + name: "file at module root", + startAt: "testdata/simple_module/main.go", + expected: "example.com/project", + }, + { + name: "directory at module root", + startAt: "testdata/simple_module", + expected: "example.com/project", + }, + { + name: "file in subdirectory", + startAt: "testdata/simple_module/pkg/utils.go", + expected: "example.com/project/pkg", + }, + { + name: "directory in subdirectory", + startAt: "testdata/simple_module/pkg", + expected: "example.com/project/pkg", + }, + { + name: "nested module file", + startAt: "testdata/nested_module/lib.go", + expected: "example.com/nested", + }, + { + name: "nested module directory", + startAt: "testdata/nested_module", + expected: "example.com/nested", + }, + { + name: "path within module", + startAt: "testdata/no_module/orphan.go", + expected: "github.com/cweill/gotests/internal/gomod/testdata/no_module", + }, + { + name: "nonexistent path", + startAt: "/tmp/nonexistent/path/file.go", + hasError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := GetFullImportPath(tt.startAt) + if tt.hasError { + if err == nil { + t.Errorf("expected error but got none") + } + } else { + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if result != tt.expected { + t.Errorf("expected %q, got %q", tt.expected, result) + } + } + }) + } +} + +func TestFindGoMod(t *testing.T) { + tests := []struct { + name string + startDir string + expected string + hasError bool + }{ + { + name: "go.mod in current directory", + startDir: "testdata/simple_module", + expected: "testdata/simple_module", + }, + { + name: "go.mod in subdirectory", + startDir: "testdata/simple_module/pkg", + expected: "testdata/simple_module", + }, + { + name: "no go.mod found", + startDir: "/tmp", + hasError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := findGoMod(tt.startDir) + if tt.hasError { + if err == nil { + t.Errorf("expected error but got none") + } + } else { + if err != nil { + t.Errorf("unexpected error: %v", err) + } + // Convert to absolute path for comparison + expectedAbs, _ := filepath.Abs(tt.expected) + resultAbs, _ := filepath.Abs(result) + if resultAbs != expectedAbs { + t.Errorf("expected %q, got %q", expectedAbs, resultAbs) + } + } + }) + } +} + +func TestParseModulePath(t *testing.T) { + tests := []struct { + name string + modRoot string + expected string + hasError bool + }{ + { + name: "valid go.mod", + modRoot: "testdata/simple_module", + expected: "example.com/project", + }, + { + name: "nested module go.mod", + modRoot: "testdata/nested_module", + expected: "example.com/nested", + }, + { + name: "nonexistent go.mod", + modRoot: "/tmp/nonexistent", + hasError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := parseModulePath(tt.modRoot) + if tt.hasError { + if err == nil { + t.Errorf("expected error but got none") + } + } else { + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if result != tt.expected { + t.Errorf("expected %q, got %q", tt.expected, result) + } + } + }) + } +} + +// Test with the actual gotests module +func TestGetFullImportPath_CurrentModule(t *testing.T) { + // Test with the gotests module itself + result, err := GetFullImportPath("gomod.go") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expected := "github.com/cweill/gotests/internal/gomod" + if result != expected { + t.Errorf("expected %q, got %q", expected, result) + } +} + +func TestGetFullImportPath_EdgeCases(t *testing.T) { + // Test with current directory (when running from internal/gomod) + result, err := GetFullImportPath(".") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expected := "github.com/cweill/gotests/internal/gomod" + if result != expected { + t.Errorf("expected %q, got %q", expected, result) + } + + // Test with absolute path + absPath, _ := filepath.Abs("gomod.go") + result, err = GetFullImportPath(absPath) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expected = "github.com/cweill/gotests/internal/gomod" + if result != expected { + t.Errorf("expected %q, got %q", expected, result) + } +} diff --git a/internal/gomod/testdata/nested_module/go.mod b/internal/gomod/testdata/nested_module/go.mod new file mode 100644 index 0000000..24235b7 --- /dev/null +++ b/internal/gomod/testdata/nested_module/go.mod @@ -0,0 +1,3 @@ +module example.com/nested + +go 1.21 \ No newline at end of file diff --git a/internal/gomod/testdata/nested_module/lib.go b/internal/gomod/testdata/nested_module/lib.go new file mode 100644 index 0000000..f8375f6 --- /dev/null +++ b/internal/gomod/testdata/nested_module/lib.go @@ -0,0 +1,5 @@ +package lib + +func Add(a, b int) int { + return a + b +} diff --git a/internal/gomod/testdata/no_module/orphan.go b/internal/gomod/testdata/no_module/orphan.go new file mode 100644 index 0000000..3a2e5d0 --- /dev/null +++ b/internal/gomod/testdata/no_module/orphan.go @@ -0,0 +1,3 @@ +package orphan + +func DoSomething() {} diff --git a/internal/gomod/testdata/simple_module/go.mod b/internal/gomod/testdata/simple_module/go.mod new file mode 100644 index 0000000..7f6f2de --- /dev/null +++ b/internal/gomod/testdata/simple_module/go.mod @@ -0,0 +1,3 @@ +module example.com/project + +go 1.21 \ No newline at end of file diff --git a/internal/gomod/testdata/simple_module/main.go b/internal/gomod/testdata/simple_module/main.go new file mode 100644 index 0000000..a3dd973 --- /dev/null +++ b/internal/gomod/testdata/simple_module/main.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("Hello, World!") +} diff --git a/internal/gomod/testdata/simple_module/pkg/utils.go b/internal/gomod/testdata/simple_module/pkg/utils.go new file mode 100644 index 0000000..909ef97 --- /dev/null +++ b/internal/gomod/testdata/simple_module/pkg/utils.go @@ -0,0 +1,7 @@ +package pkg + +import "strings" + +func ToUpper(s string) string { + return strings.ToUpper(s) +} From 21b7a08fd06cef03c922f2df80457853e0f3b05e Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 28 Oct 2025 00:26:55 +0300 Subject: [PATCH 2/3] feat(gotests): add package_test flag to generate tests in _test package Introduce a new PackageTest option in Options, Header, and render logic to support generating tests in a separate `_test` package. Update import handling, templates, and related tests. Add corresponding test data for the new behavior. --- gotests.go | 16 ++++++ gotests_test.go | 13 ++++- internal/ai/e2e_test.go | 2 +- internal/models/models.go | 9 +-- internal/output/options.go | 8 ++- internal/render/render.go | 9 ++- internal/render/render_test.go | 4 +- internal/render/templates/call.tmpl | 2 +- internal/render/templates/function.tmpl | 14 ++--- internal/render/templates/header.tmpl | 2 +- ...ons_filtering_exported_with_packagetest.go | 55 +++++++++++++++++++ 11 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 testdata/goldens/multiple_functions_filtering_exported_with_packagetest.go diff --git a/gotests.go b/gotests.go index e6eaed5..a05b888 100644 --- a/gotests.go +++ b/gotests.go @@ -10,6 +10,7 @@ import ( "sort" "sync" + "github.com/cweill/gotests/internal/gomod" "github.com/cweill/gotests/internal/goparser" "github.com/cweill/gotests/internal/input" "github.com/cweill/gotests/internal/models" @@ -21,6 +22,7 @@ type Options struct { Only *regexp.Regexp // Includes only functions that match. Exclude *regexp.Regexp // Excludes functions that match. Exported bool // Include only exported methods + PackageTest bool // Adds _test package suffix for tests PrintInputs bool // Print function parameters in error messages Subtests bool // Print tests using Go 1.7 subtests Parallel bool // Print tests that runs the subtests in parallel. @@ -121,6 +123,16 @@ func generateTest(src models.Path, files []models.Path, opt *Options) (*Generate if err != nil { return nil, err } + if opt.PackageTest && opt.Exported { + fullImportPath, fullImportPathErr := gomod.GetFullImportPath(string(src)) + if fullImportPathErr != nil { + return nil, fullImportPathErr + } + h.Imports = append(h.Imports, &models.Import{ + Name: h.Package, + Path: fmt.Sprintf("%q", fullImportPath), + }) + } funcs := testableFuncs(sr.Funcs, opt.Only, opt.Exclude, opt.Exported, tf) if len(funcs) == 0 { return nil, nil @@ -129,6 +141,7 @@ func generateTest(src models.Path, files []models.Path, opt *Options) (*Generate options := output.Options{ PrintInputs: opt.PrintInputs, Subtests: opt.Subtests, + PackageTest: opt.PackageTest, Parallel: opt.Parallel, Named: opt.Named, UseGoCmp: opt.UseGoCmp, @@ -142,6 +155,9 @@ func generateTest(src models.Path, files []models.Path, opt *Options) (*Generate AIMinCases: opt.AIMinCases, AIMaxCases: opt.AIMaxCases, } + if opt.PackageTest { + h.PackageTest = true + } b, err := options.Process(h, funcs) if err != nil { diff --git a/gotests_test.go b/gotests_test.go index 2bbb2b3..f88039e 100644 --- a/gotests_test.go +++ b/gotests_test.go @@ -22,6 +22,7 @@ func TestGenerateTests(t *testing.T) { only *regexp.Regexp excl *regexp.Regexp exported bool + packageTest bool printInputs bool subtests bool parallel bool @@ -438,6 +439,15 @@ func TestGenerateTests(t *testing.T) { }, want: mustReadAndFormatGoFile(t, "testdata/goldens/multiple_functions_filtering_exported.go"), }, + { + name: "Multiple functions filtering exported and _test package", + args: args{ + srcPath: `testdata/test_filter.go`, + exported: true, + packageTest: true, + }, + want: mustReadAndFormatGoFile(t, "testdata/goldens/multiple_functions_filtering_exported_with_packagetest.go"), + }, { name: "Multiple functions filtering exported with only", args: args{ @@ -891,6 +901,7 @@ func TestGenerateTests(t *testing.T) { Only: tt.args.only, Exclude: tt.args.excl, Exported: tt.args.exported, + PackageTest: tt.args.packageTest, PrintInputs: tt.args.printInputs, Subtests: tt.args.subtests, Parallel: tt.args.parallel, @@ -948,7 +959,7 @@ func mustReadAndFormatGoFile(t *testing.T, filename string) string { func outputResult(t *testing.T, tmpDir, testName string, got []byte) { tmpResult := path.Join(tmpDir, toSnakeCase(testName)+".go") - if err := ioutil.WriteFile(tmpResult, got, 0644); err != nil { + if err := ioutil.WriteFile(tmpResult, got, 0o644); err != nil { t.Errorf("ioutil.WriteFile: %v", err) } t.Logf("%s", tmpResult) diff --git a/internal/ai/e2e_test.go b/internal/ai/e2e_test.go index f5fd68c..74915c3 100644 --- a/internal/ai/e2e_test.go +++ b/internal/ai/e2e_test.go @@ -206,7 +206,7 @@ func TestE2E_OllamaGeneration_ValidatesStructure(t *testing.T) { // Render test function with same parameters as CLI uses // (printInputs=false, subtests=true, named=false, parallel=false, useGoCmp=false) - if err := r.TestFunction(&buf, targetFunc, false, true, false, false, false, nil, aiCases); err != nil { + if err := r.TestFunction(&buf, targetFunc, false, true, false, false, false, nil, aiCases, false, ""); err != nil { t.Fatalf("Failed to render test function: %v", err) } diff --git a/internal/models/models.go b/internal/models/models.go index efc40df..ec94cfe 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -185,10 +185,11 @@ type Import struct { // Header represents the header of a Go file, including package name, imports, and any code between imports and declarations. type Header struct { - Comments []string - Package string - Imports []*Import - Code []byte + Comments []string + Package string + Imports []*Import + Code []byte + PackageTest bool } // Path represents a file system path. diff --git a/internal/output/options.go b/internal/output/options.go index b1af782..b6461a9 100755 --- a/internal/output/options.go +++ b/internal/output/options.go @@ -20,6 +20,7 @@ import ( type Options struct { PrintInputs bool Subtests bool + PackageTest bool Parallel bool Named bool UseGoCmp bool @@ -68,10 +69,13 @@ func (o *Options) Process(head *models.Header, funcs []*models.Function) ([]byte } // format file - out, err := imports.Process(tf.Name(), b.Bytes(), nil) + newVar := b.Bytes() + fmt.Println(string(newVar)) + out, err := imports.Process(tf.Name(), newVar, nil) if err != nil { return nil, fmt.Errorf("imports.Process: %v", err) } + fmt.Println(string(out)) return out, nil } @@ -153,7 +157,7 @@ func (o *Options) writeTests(w io.Writer, head *models.Header, funcs []*models.F } } - err := o.render.TestFunction(b, fun, o.PrintInputs, o.Subtests, o.Named, o.Parallel, o.UseGoCmp, o.TemplateParams, aiCases) + err := o.render.TestFunction(b, fun, o.PrintInputs, o.Subtests, o.Named, o.Parallel, o.UseGoCmp, o.TemplateParams, aiCases, o.PackageTest, head.Package) if err != nil { return fmt.Errorf("render.TestFunction: %v", err) } diff --git a/internal/render/render.go b/internal/render/render.go index a6b29fa..6c62697 100755 --- a/internal/render/render.go +++ b/internal/render/render.go @@ -102,11 +102,16 @@ func (r *Render) TestFunction( parallel bool, useGoCmp bool, params map[string]interface{}, - aiCases []interface{}) error { + aiCases []interface{}, + packageTest bool, + packageName string, +) error { return r.tmpls.ExecuteTemplate(w, "function", struct { *models.Function PrintInputs bool Subtests bool + PackageName string + PackageTest bool Parallel bool Named bool UseGoCmp bool @@ -121,5 +126,7 @@ func (r *Render) TestFunction( UseGoCmp: useGoCmp, TemplateParams: params, AIGeneratedCases: aiCases, + PackageTest: packageTest, + PackageName: packageName, }) } diff --git a/internal/render/render_test.go b/internal/render/render_test.go index 11a8a0c..79d2fb8 100644 --- a/internal/render/render_test.go +++ b/internal/render/render_test.go @@ -148,7 +148,7 @@ func TestRender_TestFunction(t *testing.T) { }, } - err := r.TestFunction(buf, fn, false, false, false, false, false, nil, nil) + err := r.TestFunction(buf, fn, false, false, false, false, false, nil, nil, false, "") if err != nil { t.Errorf("Render.TestFunction() error = %v", err) } @@ -203,7 +203,7 @@ func TestRender_TestFunction_WithOptions(t *testing.T) { }, } - err := r.TestFunction(buf, fn, tt.printInputs, tt.subtests, tt.named, tt.parallel, tt.useGoCmp, nil, nil) + err := r.TestFunction(buf, fn, tt.printInputs, tt.subtests, tt.named, tt.parallel, tt.useGoCmp, nil, nil, false, "") if err != nil { t.Errorf("Render.TestFunction() error = %v", err) } diff --git a/internal/render/templates/call.tmpl b/internal/render/templates/call.tmpl index 3e3db1a..d282c0a 100644 --- a/internal/render/templates/call.tmpl +++ b/internal/render/templates/call.tmpl @@ -1 +1 @@ -{{define "call"}}{{with .Receiver}}{{if not .IsStruct}}tt.{{end}}{{Receiver .}}.{{end}}{{.Name}}{{TypeArgs .}}({{range $i, $el := .Parameters}}{{if $i}}, {{end}}{{if not .IsWriter}}tt.args.{{end}}{{Param .}}{{if .Type.IsVariadic}}...{{end}}{{end}}){{end}} \ No newline at end of file +{{define "call"}}{{with .Receiver}}{{if not .IsStruct}}tt.{{end}}{{Receiver .}}.{{end}}{{if and .PackageTest (not .Receiver)}}{{.PackageName}}.{{end}}{{.Name}}{{TypeArgs .}}({{range $i, $el := .Parameters}}{{if $i}}, {{end}}{{if not .IsWriter}}tt.args.{{end}}{{Param .}}{{if .Type.IsVariadic}}...{{end}}{{end}}){{end}} diff --git a/internal/render/templates/function.tmpl b/internal/render/templates/function.tmpl index 204d42a..7559f7c 100644 --- a/internal/render/templates/function.tmpl +++ b/internal/render/templates/function.tmpl @@ -29,7 +29,7 @@ func {{.TestName}}(t *testing.T) { {{- if and .IsStruct .Fields}} fields fields {{- else}} - {{Receiver .}} {{FieldType $ .Field}} + {{Receiver .}} {{if $.PackageTest}}*{{$.PackageName}}.{{ReceiverType $ .}}{{else}}{{FieldType $ .Field}}{{end}} {{- end}} {{- end}} {{- if .TestParameters}} @@ -84,14 +84,12 @@ func {{.TestName}}(t *testing.T) { t.Run({{if .Named}}name{{else}}tt.name{{end}}, func(t *testing.T) { {{- if .Parallel}}t.Parallel(){{end}} {{- end}} - {{- with .Receiver}} - {{- if .IsStruct}} - {{Receiver .}} := {{if .Type.IsStar}}&{{end}}{{ReceiverType $ .}}{ - {{- range .Fields}} - {{.Name}}: tt.fields.{{Field .}}, - {{- end}} - } + {{- if and .Receiver .Receiver.IsStruct}} + {{Receiver .Receiver}} := {{if .Receiver.Type.IsStar}}&{{if .PackageTest}}{{.PackageName}}.{{end}}{{end}}{{ReceiverType $ .Receiver}}{ + {{- range .Receiver.Fields}} + {{.Name}}: tt.fields.{{Field .}}, {{- end}} + } {{- end}} {{- range .Parameters}} {{- if .IsWriter}} diff --git a/internal/render/templates/header.tmpl b/internal/render/templates/header.tmpl index 245569d..37a1008 100644 --- a/internal/render/templates/header.tmpl +++ b/internal/render/templates/header.tmpl @@ -1,7 +1,7 @@ {{define "header"}} {{range .Comments}}{{.}} {{end -}} -package {{.Package}} +package {{.Package}}{{if .PackageTest}}_test{{end}} import ( {{range .Imports}}{{.Name}} {{.Path}} diff --git a/testdata/goldens/multiple_functions_filtering_exported_with_packagetest.go b/testdata/goldens/multiple_functions_filtering_exported_with_packagetest.go new file mode 100644 index 0000000..47ee329 --- /dev/null +++ b/testdata/goldens/multiple_functions_filtering_exported_with_packagetest.go @@ -0,0 +1,55 @@ +package testdata_test + +import ( + "reflect" + "testing" + + testdata "github.com/cweill/gotests/testdata" +) + +func TestFooFilter(t *testing.T) { + type args struct { + strs []string + } + tests := []struct { + name string + args args + want []*Bar + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + got, err := testdata.FooFilter(tt.args.strs) + if (err != nil) != tt.wantErr { + t.Errorf("%q. FooFilter() error = %v, wantErr %v", tt.name, err, tt.wantErr) + continue + } + if tt.wantErr { + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("%q. FooFilter() = %v, want %v", tt.name, got, tt.want) + } + } +} + +func TestBar_BarFilter(t *testing.T) { + type args struct { + i interface{} + } + tests := []struct { + name string + b *testdata.Bar + args args + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + b := &testdata.Bar{} + if err := b.BarFilter(tt.args.i); (err != nil) != tt.wantErr { + t.Errorf("%q. Bar.BarFilter() error = %v, wantErr %v", tt.name, err, tt.wantErr) + } + } +} From df5f5e00ff7607173ebb7208e14502abac3ae00a Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 28 Oct 2025 00:34:51 +0300 Subject: [PATCH 3/3] refactor(output): remove debug prints and simplify imports processing Removed temporary variable and console output used for debugging in `options.go`. Directly pass `b.Bytes()` to `imports.Process` and eliminate unnecessary `fmt.Println` statements, cleaning up the code without altering functionality. --- internal/output/options.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/output/options.go b/internal/output/options.go index b6461a9..8074a65 100755 --- a/internal/output/options.go +++ b/internal/output/options.go @@ -69,13 +69,10 @@ func (o *Options) Process(head *models.Header, funcs []*models.Function) ([]byte } // format file - newVar := b.Bytes() - fmt.Println(string(newVar)) - out, err := imports.Process(tf.Name(), newVar, nil) + out, err := imports.Process(tf.Name(), b.Bytes(), nil) if err != nil { return nil, fmt.Errorf("imports.Process: %v", err) } - fmt.Println(string(out)) return out, nil }