From d23881c0069afc8e31ea53ca99f4844496de5db9 Mon Sep 17 00:00:00 2001 From: Will-thom <116388885+Will-thom@users.noreply.github.com> Date: Wed, 3 Jun 2026 03:35:26 -0300 Subject: [PATCH] test: add output file e2e matrix --- cmd/prmaven/acceptance_test.go | 125 +++++++++++++++++++++++++++++++++ docs/testing.md | 2 + 2 files changed, 127 insertions(+) diff --git a/cmd/prmaven/acceptance_test.go b/cmd/prmaven/acceptance_test.go index d3f640d..d5772e8 100644 --- a/cmd/prmaven/acceptance_test.go +++ b/cmd/prmaven/acceptance_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "errors" + "os" "os/exec" "path/filepath" "runtime" @@ -91,6 +92,130 @@ func TestCLIAcceptanceSuite(t *testing.T) { } } +type acceptanceOutputCase struct { + name string + format string + outputFile string + wantExitCode int + wantStdout []string + wantFileContains []string + wantFindingCount int + wantJSON bool +} + +func TestCLIOutputFileMatrix(t *testing.T) { + binary := buildAcceptanceBinary(t) + + tests := []acceptanceOutputCase{ + { + name: "text stdout without output file", + format: "text", + wantExitCode: 1, + wantStdout: []string{ + "PR Maven CLI - Maven failure context", + "Modules: 3 | Reports: 2 | Findings: 2", + "maven-surefire-plugin", + "maven-failsafe-plugin", + }, + }, + { + name: "json stdout without output file", + format: "json", + wantExitCode: 1, + wantJSON: true, + wantFindingCount: 2, + }, + { + name: "text output file", + format: "text", + outputFile: "prmaven-report.txt", + wantExitCode: 1, + wantFileContains: []string{ + "PR Maven CLI - Maven failure context", + "Modules: 3 | Reports: 2 | Findings: 2", + "maven-surefire-plugin", + "maven-failsafe-plugin", + }, + }, + { + name: "json output file", + format: "json", + outputFile: "prmaven-report.json", + wantExitCode: 1, + wantJSON: true, + wantFindingCount: 2, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + outputDir := t.TempDir() + outputPath := filepath.Join(outputDir, "unused-report") + args := []string{"why", "-project", "../../demo/multi-module-failure"} + if tt.format != "text" { + args = append(args, "-format", tt.format) + } + if tt.outputFile != "" { + outputPath = filepath.Join(outputDir, tt.outputFile) + args = append(args, "-output", outputPath) + } + + stdout, stderr, exitCode := runAcceptanceBinary(t, binary, args...) + if exitCode != tt.wantExitCode { + t.Fatalf("exit code = %d, want %d\nstdout:\n%s\nstderr:\n%s", exitCode, tt.wantExitCode, stdout, stderr) + } + if stderr != "" { + t.Fatalf("stderr = %q, want empty", stderr) + } + + if tt.outputFile == "" { + if stdout == "" { + t.Fatal("stdout is empty, want report output when -output is absent") + } + if _, err := os.Stat(outputPath); !errors.Is(err, os.ErrNotExist) { + t.Fatalf("unexpected output file at %s when -output is absent", outputPath) + } + assertAcceptanceOutput(t, stdout, tt) + return + } + + if stdout != "" { + t.Fatalf("stdout = %q, want empty when -output is set", stdout) + } + + output, err := os.ReadFile(outputPath) + if err != nil { + t.Fatalf("read output file: %v", err) + } + assertAcceptanceOutput(t, string(output), tt) + }) + } +} + +func assertAcceptanceOutput(t *testing.T, output string, tt acceptanceOutputCase) { + t.Helper() + + for _, expected := range append(tt.wantStdout, tt.wantFileContains...) { + if !strings.Contains(output, expected) { + t.Fatalf("output missing %q\n%s", expected, output) + } + } + + if tt.wantJSON { + var report struct { + Summary struct { + FindingCount int `json:"findingCount"` + } `json:"summary"` + } + if err := json.Unmarshal([]byte(output), &report); err != nil { + t.Fatalf("output is not valid JSON: %v\n%s", err, output) + } + if report.Summary.FindingCount != tt.wantFindingCount { + t.Fatalf("finding count = %d, want %d", report.Summary.FindingCount, tt.wantFindingCount) + } + } +} + func buildAcceptanceBinary(t *testing.T) string { t.Helper() diff --git a/docs/testing.md b/docs/testing.md index 8cc58c8..ef5d061 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -87,6 +87,8 @@ Coverage includes: - non-zero exit when findings exist; - zero exit when no findings exist; - parseable JSON output for both finding and no-finding workflows; +- output-file behavior for text and JSON with temporary test files; +- stdout behavior when `-output` is absent; - invalid command and invalid format handling. ### Documented Command Smoke Tests