|
27 | 27 | // Runner describes the test run parameters and raw test outputs |
28 | 28 | type Runner struct { |
29 | 29 | ProjectPath string // Path to the Go project directory. |
30 | | - GoProject string // Go project package name. |
| 30 | + prettyProjectPath string // Go project package path, formatted for pretty printing. |
31 | 31 | Verbose bool // If true, provides detailed logging. |
32 | 32 | RunCount int // Number of times to run the tests. |
33 | 33 | UseRace bool // Enable race detector. |
@@ -76,7 +76,7 @@ func (r *Runner) RunTestPackages(packages []string) (*reports.TestReport, error) |
76 | 76 | return nil, fmt.Errorf("failed to parse test results: %w", err) |
77 | 77 | } |
78 | 78 | report := &reports.TestReport{ |
79 | | - GoProject: r.GoProject, |
| 79 | + GoProject: r.prettyProjectPath, |
80 | 80 | RaceDetection: r.UseRace, |
81 | 81 | ExcludedTests: r.SkipTests, |
82 | 82 | SelectedTests: r.SelectTests, |
@@ -112,7 +112,7 @@ func (r *Runner) RunTestCmd(testCmd []string) (*reports.TestReport, error) { |
112 | 112 | } |
113 | 113 |
|
114 | 114 | report := &reports.TestReport{ |
115 | | - GoProject: r.GoProject, |
| 115 | + GoProject: r.prettyProjectPath, |
116 | 116 | RaceDetection: r.UseRace, |
117 | 117 | ExcludedTests: r.SkipTests, |
118 | 118 | SelectedTests: r.SelectTests, |
@@ -173,6 +173,11 @@ func (r *Runner) runTestPackage(packageName string) (string, bool, error) { |
173 | 173 | } |
174 | 174 | defer tmpFile.Close() |
175 | 175 |
|
| 176 | + r.prettyProjectPath, err = prettyProjectPath(r.ProjectPath) |
| 177 | + if err != nil { |
| 178 | + r.prettyProjectPath = r.ProjectPath |
| 179 | + log.Warn().Err(err).Str("projectPath", r.ProjectPath).Msg("Failed to get pretty project path") |
| 180 | + } |
176 | 181 | // Run the command with output directed to the file |
177 | 182 | cmd := exec.Command("go", args...) |
178 | 183 | cmd.Dir = r.ProjectPath |
@@ -633,3 +638,42 @@ func parseSubTest(testName string) (parentTestName, subTestName string) { |
633 | 638 | } |
634 | 639 | return parts[0], parts[1] |
635 | 640 | } |
| 641 | + |
| 642 | +// prettyProjectPath returns the project path formatted for pretty printing in results. |
| 643 | +func prettyProjectPath(projectPath string) (string, error) { |
| 644 | + // Walk up the directory structure to find go.mod |
| 645 | + absPath, err := filepath.Abs(projectPath) |
| 646 | + if err != nil { |
| 647 | + return "", fmt.Errorf("failed to resolve absolute path: %w", err) |
| 648 | + } |
| 649 | + dir := absPath |
| 650 | + for { |
| 651 | + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { |
| 652 | + break |
| 653 | + } |
| 654 | + |
| 655 | + parent := filepath.Dir(dir) |
| 656 | + if parent == dir { // Reached the root without finding go.mod |
| 657 | + return "", fmt.Errorf("go.mod not found in project path, started at %s, ended at %s", projectPath, dir) |
| 658 | + } |
| 659 | + dir = parent |
| 660 | + } |
| 661 | + |
| 662 | + // Read go.mod to extract the module path |
| 663 | + goModPath := filepath.Join(dir, "go.mod") |
| 664 | + goModData, err := os.ReadFile(goModPath) |
| 665 | + if err != nil { |
| 666 | + return "", fmt.Errorf("failed to read go.mod: %w", err) |
| 667 | + } |
| 668 | + |
| 669 | + for _, line := range strings.Split(string(goModData), "\n") { |
| 670 | + if strings.HasPrefix(line, "module ") { |
| 671 | + goProject := strings.TrimSpace(strings.TrimPrefix(line, "module ")) |
| 672 | + relativePath := strings.TrimPrefix(projectPath, dir) |
| 673 | + relativePath = strings.TrimLeft(relativePath, string(os.PathSeparator)) |
| 674 | + return filepath.Join(goProject, relativePath), nil |
| 675 | + } |
| 676 | + } |
| 677 | + |
| 678 | + return "", fmt.Errorf("module path not found in go.mod") |
| 679 | +} |
0 commit comments