diff options
Diffstat (limited to 'languages/go/tests')
| -rw-r--r-- | languages/go/tests/coverage_summary_test.go | 142 | ||||
| -rw-r--r-- | languages/go/tests/go.mod | 3 |
2 files changed, 145 insertions, 0 deletions
diff --git a/languages/go/tests/coverage_summary_test.go b/languages/go/tests/coverage_summary_test.go new file mode 100644 index 0000000..6b2fb44 --- /dev/null +++ b/languages/go/tests/coverage_summary_test.go @@ -0,0 +1,142 @@ +// Black-box tests for the Go bundle coverage-summary script. +// +// The script ships into a project's .claude/scripts/ and runs via `go run`, so +// these tests exercise the real CLI rather than importing it: build a throwaway +// module (go.mod + source files + a cover.out profile), run the script against +// it, and assert on stdout. Keeping the test in its own module here means the +// shipped script dir stays test-free. +// +// Normal / Boundary / Error coverage at the behavior level: missing-file +// detection, the file-weighted number, all-tracked, ignoring _test.go, and a +// missing-report error. +package gocovtest + +import ( + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" +) + +// scriptPath resolves coverage-summary.go relative to this test file. +func scriptPath(t *testing.T) string { + t.Helper() + _, thisFile, _, ok := runtime.Caller(0) + if !ok { + t.Fatal("cannot locate test file") + } + p := filepath.Join(filepath.Dir(thisFile), "..", "claude", "scripts", "coverage-summary.go") + abs, err := filepath.Abs(p) + if err != nil { + t.Fatal(err) + } + return abs +} + +// fixture writes a go.mod, the given source files, and a cover.out under a temp +// module root. sources maps relpath -> contents; profile is the raw cover.out. +func fixture(t *testing.T, sources map[string]string, profile string) string { + t.Helper() + root := t.TempDir() + write := func(rel, body string) { + full := filepath.Join(root, rel) + if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(full, []byte(body), 0o644); err != nil { + t.Fatal(err) + } + } + write("go.mod", "module example.com/m\n\ngo 1.26\n") + for rel, body := range sources { + write(rel, body) + } + write("cover.out", profile) + return root +} + +// run executes the script against a fixture root, returning combined output + err. +func run(t *testing.T, root, sourceDir string) (string, error) { + t.Helper() + cmd := exec.Command("go", "run", scriptPath(t), + filepath.Join(root, "cover.out"), filepath.Join(root, sourceDir), root) + out, err := cmd.CombinedOutput() + return string(out), err +} + +func TestMissingFileSurfacedAndCountedZero(t *testing.T) { + root := fixture(t, + map[string]string{ + "calc/calc.go": "package calc\n\nfunc Add(a, b int) int { return a + b }\n", + "calc/untested.go": "package calc\n\nfunc Mul(a, b int) int { return a * b }\n", + }, + // calc.go fully covered (2/2 stmts); untested.go absent from the profile. + "mode: set\nexample.com/m/calc/calc.go:3.40,3.56 2 1\n", + ) + out, err := run(t, root, ".") + if err != nil { + t.Fatalf("script failed: %v\n%s", err, out) + } + if !strings.Contains(out, "calc/untested.go") { + t.Errorf("missing file not surfaced:\n%s", out) + } + if !strings.Contains(out, "0%") { + t.Errorf("missing-as-0%% note absent:\n%s", out) + } + // calc.go = 100%, untested.go missing = 0% -> 50.0% + if !strings.Contains(out, "50.0%") { + t.Errorf("expected project number 50.0%%:\n%s", out) + } +} + +func TestAllTrackedNoMissing(t *testing.T) { + root := fixture(t, + map[string]string{"calc/calc.go": "package calc\n\nfunc Add(a, b int) int { return a + b }\n"}, + "mode: set\nexample.com/m/calc/calc.go:3.40,3.56 2 1\n", + ) + out, err := run(t, root, ".") + if err != nil { + t.Fatalf("script failed: %v\n%s", err, out) + } + if !strings.Contains(out, "Not in coverage report: 0 file") { + t.Errorf("expected zero missing files:\n%s", out) + } + if !strings.Contains(out, "100.0%") { + t.Errorf("expected 100.0%% project number:\n%s", out) + } +} + +func TestTestFilesAreNotCountedAsSource(t *testing.T) { + root := fixture(t, + map[string]string{ + "calc/calc.go": "package calc\n\nfunc Add(a, b int) int { return a + b }\n", + "calc/calc_test.go": "package calc\n\nimport \"testing\"\n\nfunc TestX(t *testing.T) {}\n", + }, + "mode: set\nexample.com/m/calc/calc.go:3.40,3.56 2 1\n", + ) + out, err := run(t, root, ".") + if err != nil { + t.Fatalf("script failed: %v\n%s", err, out) + } + if strings.Contains(out, "calc_test.go") { + t.Errorf("_test.go wrongly counted as source:\n%s", out) + } + if !strings.Contains(out, "100.0%") { + t.Errorf("expected 100.0%% (test file excluded):\n%s", out) + } +} + +func TestMissingReportErrors(t *testing.T) { + root := fixture(t, + map[string]string{"calc/calc.go": "package calc\n"}, + "mode: set\n", + ) + cmd := exec.Command("go", "run", scriptPath(t), + filepath.Join(root, "does-not-exist.out"), root, root) + out, err := cmd.CombinedOutput() + if err == nil { + t.Errorf("expected non-zero exit for missing report; output:\n%s", out) + } +} diff --git a/languages/go/tests/go.mod b/languages/go/tests/go.mod new file mode 100644 index 0000000..db72cb1 --- /dev/null +++ b/languages/go/tests/go.mod @@ -0,0 +1,3 @@ +module gocovtest + +go 1.26 |
