package main import ( "fmt" "strings" "time" ) func evaluateFile(path string, results []CommandResult, fileError string) TestResult { if fileError != "" { return TestResult{ Path: path, Passed: false, CommandCount: len(results), Error: fileError, } } var failures []FailedCommand for _, r := range results { cmd := r.Command outputMatches := matchOutput(cmd.Expected, r.Actual) var exitCodeMismatch bool switch cmd.ExitCodeType { case ExitCodeNone: exitCodeMismatch = r.ExitCode != 0 case ExitCodeWildcard: exitCodeMismatch = r.ExitCode == 0 case ExitCodeExact: exitCodeMismatch = r.ExitCode != cmd.ExitCodeValue } if !outputMatches || exitCodeMismatch { var diffLines []DiffLine if !outputMatches { diffLines = diff(cmd.Expected, r.Actual) } failures = append(failures, FailedCommand{ Result: r, DiffLines: diffLines, ExitCodeMismatch: exitCodeMismatch, }) } } return TestResult{ Path: path, Passed: len(failures) == 0, CommandCount: len(results), Failures: failures, } } func formatFailure(t TestResult) string { var lines []string lines = append(lines, red("FAIL "+t.Path)) if t.Error != "" { lines = append(lines, " "+red(t.Error)) return strings.Join(lines, "\n") } for _, f := range t.Failures { lines = append(lines, "") lines = append(lines, " "+dim("$")+" "+f.Result.Command.Cmd) if len(f.DiffLines) > 0 { lines = append(lines, red(" expected:")) for _, dl := range f.DiffLines { switch dl.Kind { case "expected": lines = append(lines, red(" > ")+dl.Text) case "equal": lines = append(lines, " "+dl.Text) case "context": lines = append(lines, " "+dim(dl.Text)) } } lines = append(lines, green(" actual:")) for _, dl := range f.DiffLines { switch dl.Kind { case "actual": lines = append(lines, green(" > ")+dl.Text) case "equal": lines = append(lines, " "+dl.Text) case "context": lines = append(lines, " "+dim(dl.Text)) } } } if f.ExitCodeMismatch { cmd := f.Result.Command var expectedStr string switch cmd.ExitCodeType { case ExitCodeNone: expectedStr = "0" case ExitCodeWildcard: expectedStr = "non-zero" case ExitCodeExact: expectedStr = fmt.Sprintf("%d", cmd.ExitCodeValue) } lines = append(lines, red(fmt.Sprintf(" expected exit code: %s", expectedStr))) lines = append(lines, green(fmt.Sprintf(" actual exit code: %d", f.Result.ExitCode))) } } return strings.Join(lines, "\n") } func formatSummary(results []TestResult, elapsed time.Duration) string { totalCommands := 0 failedCommands := 0 for _, r := range results { totalCommands += r.CommandCount failedCommands += len(r.Failures) } passedCommands := totalCommands - failedCommands var parts []string if passedCommands > 0 { parts = append(parts, green(fmt.Sprintf("%d passed", passedCommands))) } if failedCommands > 0 { parts = append(parts, red(fmt.Sprintf("%d failed", failedCommands))) } var timeStr string if elapsed < time.Second { timeStr = fmt.Sprintf("%dms", elapsed.Milliseconds()) } else { timeStr = fmt.Sprintf("%.1fs", elapsed.Seconds()) } return fmt.Sprintf("%s in %s", strings.Join(parts, ", "), timeStr) }