Ctrl K
ComunidadGuías…

scripts/check_mutation_total_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package scripts_test

import (
	"errors"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
)

type mutationRun struct {
	console string
	summary string
}

func runMutationTotalCheck(t *testing.T, reports map[string]string) (mutationRun, error) {
	t.Helper()
	if runtime.GOOS == "windows" {
		t.Skip("the mutation total checker runs in the Linux CI job")
	}
	dir := t.TempDir()
	for name, report := range reports {
		path := filepath.Join(dir, name)
		if err := os.WriteFile(path, []byte(report), 0o600); err != nil {
			t.Fatalf("write report: %v", err)
		}
	}
	summary := filepath.Join(t.TempDir(), "summary.md")
	console, err := runMutationTotalCheckWithSummary(dir, summary)
	written, readErr := os.ReadFile(summary)
	if readErr != nil && !errors.Is(readErr, os.ErrNotExist) {
		t.Fatalf("read summary: %v", readErr)
	}
	return mutationRun{console: console, summary: string(written)}, err
}

func runMutationTotalCheckWithSummary(dir, summary string) (string, error) {
	cmd := exec.Command("bash", "check-mutation-total.sh", dir)
	cmd.Env = append(os.Environ(), "GITHUB_STEP_SUMMARY="+summary)
	out, err := cmd.CombinedOutput()
	return string(out), err
}

func mutationTotalReports() map[string]string {
	return map[string]string{
		"root-default-root.json": `{"mutants_killed":30,"mutants_lived":0,"mutants_not_covered":10,"files":[]}`,
		"root-desktop-root.json": `{"mutants_killed":20,"mutants_lived":0,"mutants_not_covered":8,"files":[]}`,
		"internal-a-d-auth.json": `{"mutants_killed":10,"mutants_lived":0,"mutants_not_covered":5,` +
			`"files":[{"file_name":"auth.go","mutations":[` +
			`{"status":"NOT COVERED","line":3,"type":"CONDITIONALS_NEGATION"},` +
			`{"status":"NOT COVERED","line":4,"type":"CONDITIONALS_BOUNDARY"}]}]}`,
	}
}

func TestMutationTotalCheckSeparatesTheTwoBuilds(t *testing.T) {
	run, err := runMutationTotalCheck(t, mutationTotalReports())
	if err != nil {
		t.Fatalf("check mutation totals: %v", err)
	}
	if !strings.Contains(run.console, "60 killed, 0 survived; uncovered 15 default, 13 desktop") {
		t.Fatalf("console = %q, want the per-build totals", run.console)
	}
}

func TestMutationTotalCheckNamesTheFilesNoTestReaches(t *testing.T) {
	run, err := runMutationTotalCheck(t, mutationTotalReports())
	if err != nil {
		t.Fatalf("check mutation totals: %v", err)
	}
	if !strings.Contains(run.summary, "## Mutation testing") {
		t.Fatalf("summary = %q, want the mutation heading", run.summary)
	}
	if !strings.Contains(run.summary, "| 2 | internal-a-d-auth | auth.go |") {
		t.Fatalf("summary = %q, want the uncovered file listed", run.summary)
	}
}

func TestMutationTotalCheckWarnsAboutASurvivingMutantWithoutFailing(t *testing.T) {
	reports := mutationTotalReports()
	reports["internal-a-d-auth.json"] = `{"mutants_killed":10,"mutants_lived":1,"mutants_not_covered":0,` +
		`"files":[{"file_name":"auth.go","mutations":[{"status":"LIVED","line":42,"type":"REMOVE_SELF_ASSIGNMENTS"}]}]}`

	run, err := runMutationTotalCheck(t, reports)
	if err != nil {
		t.Fatalf("check surviving mutant: %v", err)
	}
	if !strings.Contains(run.console, "::warning title=Mutant survived::REMOVE_SELF_ASSIGNMENTS changed auth.go:42") {
		t.Fatalf("console = %q, want a warning annotation", run.console)
	}
	if !strings.Contains(run.summary, "| internal-a-d-auth | auth.go | 42 | REMOVE_SELF_ASSIGNMENTS |") {
		t.Fatalf("summary = %q, want the survivor in the summary", run.summary)
	}
}

func TestMutationTotalCheckPrintsTheSummaryWhenActionsIsNotListening(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("the mutation total checker runs in the Linux CI job")
	}
	dir := t.TempDir()
	for name, report := range mutationTotalReports() {
		if err := os.WriteFile(filepath.Join(dir, name), []byte(report), 0o600); err != nil {
			t.Fatalf("write report: %v", err)
		}
	}

	console, err := runMutationTotalCheckWithSummary(dir, "")
	if err != nil {
		t.Fatalf("check mutation totals: %v", err)
	}
	if !strings.Contains(console, "## Mutation testing") {
		t.Fatalf("console = %q, want the summary on stdout without a step summary to write to", console)
	}
}

func TestMutationTotalCheckRejectsAMissingDesktopRootReport(t *testing.T) {
	reports := mutationTotalReports()
	delete(reports, "root-desktop-root.json")
	_, err := runMutationTotalCheck(t, reports)
	if code := exitCode(t, err); code != 11 {
		t.Fatalf("exit code = %d, want 11", code)
	}
}

func TestMutationTotalCheckRejectsAnEmptyReportDirectory(t *testing.T) {
	_, err := runMutationTotalCheck(t, map[string]string{})
	if code := exitCode(t, err); code != 11 {
		t.Fatalf("exit code = %d, want 11", code)
	}
}

func TestMutationTotalCheckRejectsAReportItCannotRead(t *testing.T) {
	reports := mutationTotalReports()
	reports["internal-a-d-auth.json"] = "not json"
	_, err := runMutationTotalCheck(t, reports)
	if code := exitCode(t, err); code != 11 {
		t.Fatalf("exit code = %d, want 11", code)
	}
}