package testsuite import ( "fmt" "os" "path/filepath" "runtime" "strings" "time" ) func (r *Runner) writeSummary(start, end time.Time) error { passed := 0 failed := 0 for _, cs := range r.results { if cs.Passed { passed++ } else { failed++ } } summary := runSummary{ RunID: r.runID, StartedAt: start.Format(time.RFC3339Nano), EndedAt: end.Format(time.RFC3339Nano), DurationMS: end.Sub(start).Milliseconds(), Stats: map[string]any{ "total": len(r.results), "passed": passed, "failed": failed, }, Environment: map[string]any{ "go_version": runtime.Version(), "os": runtime.GOOS, "arch": runtime.GOARCH, "base_url": r.baseURL, "config_source": r.originalConfigPath, "config_isolated": r.configCopyPath, "server_log": r.serverLog, "preflight_log": r.preflightLog, "retries": r.opts.Retries, "timeout_seconds": int(r.opts.Timeout.Seconds()), }, Cases: r.results, Warnings: r.warnings, } if err := writeJSONFile(filepath.Join(r.runDir, "summary.json"), summary); err != nil { return err } return os.WriteFile(filepath.Join(r.runDir, "summary.md"), []byte(r.summaryMarkdown(summary)), 0o644) } func (r *Runner) summaryMarkdown(s runSummary) string { var b strings.Builder b.WriteString("# DS2API Live Testsuite Summary\n\n") b.WriteString("**Sensitive Notice:** this run stores full raw request/response logs. Do not share artifacts publicly.\n\n") fmt.Fprintf(&b, "- Run ID: `%s`\n", s.RunID) fmt.Fprintf(&b, "- Started: `%s`\n", s.StartedAt) fmt.Fprintf(&b, "- Ended: `%s`\n", s.EndedAt) fmt.Fprintf(&b, "- Duration: `%d ms`\n", s.DurationMS) fmt.Fprintf(&b, "- Passed/Failed: `%d/%d`\n\n", s.Stats["passed"], s.Stats["failed"]) if len(s.Warnings) > 0 { b.WriteString("## Warnings\n\n") for _, w := range s.Warnings { fmt.Fprintf(&b, "- %s\n", w) } b.WriteString("\n") } b.WriteString("## Failed Cases\n\n") hasFailed := false for _, c := range s.Cases { if c.Passed { continue } hasFailed = true fmt.Fprintf(&b, "- `%s`: %s\n", c.CaseID, c.Error) if len(c.TraceIDs) > 0 { fmt.Fprintf(&b, " - trace_ids: `%s`\n", strings.Join(c.TraceIDs, ", ")) fmt.Fprintf(&b, " - grep: `rg \"%s\" %s`\n", c.TraceIDs[0], filepath.Join(r.runDir, "server.log")) } fmt.Fprintf(&b, " - artifact: `%s`\n", c.ArtifactPath) } if !hasFailed { b.WriteString("- none\n") } b.WriteString("\n## Case Table\n\n") b.WriteString("| case_id | status | duration_ms | statuses | artifact |\n") b.WriteString("|---|---:|---:|---|---|\n") for _, c := range s.Cases { status := "PASS" if !c.Passed { status = "FAIL" } fmt.Fprintf(&b, "| %s | %s | %d | %v | `%s` |\n", c.CaseID, status, c.DurationMS, c.StatusCodes, c.ArtifactPath) } return b.String() }