//go:build integration package lint import ( "context" "os" "os/exec" "path/filepath" "strings" "testing" "time" ) // judgeUnitRun runs merge-check.sh's judging of the unit level on a recorded `go test -v` output (issue 895), as it // would judge the output of the untagged run: it starts the shell, so it is an integration test. func judgeUnitRun(t *testing.T, recorded string, bound string) (string, error) { t.Helper() out := filepath.Join(t.TempDir(), "unit.out") if err := os.WriteFile(out, []byte(recorded), 0o600); err != nil { t.Fatal(err) } ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() cmd := exec.CommandContext(ctx, "sh", "merge-check.sh", "judge-unit-run", out, bound) cmd.Dir = filepath.Join("..", "..") said, err := cmd.CombinedOutput() return string(said), err } const recordedUnitRun = `=== RUN TestQuick --- PASS: TestQuick (0.01s) === RUN TestSlowOne --- PASS: TestSlowOne (2.50s) === RUN TestSlowTwo --- PASS: TestSlowTwo/sub (1.00s) --- PASS: TestSlowTwo (1.20s) --- SKIP: TestNeedsAStore (0.00s) PASS ok example.test/internal/one 2.80s === RUN TestElsewhere --- PASS: TestElsewhere (0.30s) PASS ok example.test/internal/two 0.35s ? example.test/internal/three [no test files] ` // **The unit level over its bound fails the check and names the slowest tests** (issue 895). func TestAUnitRunOverItsBoundFailsAndNamesTheSlowestTests(t *testing.T) { said, err := judgeUnitRun(t, recordedUnitRun, "1") if err == nil { t.Fatalf("a unit run of 2.80 s passed a bound of 1 s: %s", said) } for _, want := range []string{"5 tests (1 skipped)", "2.80 s (bound 1 s)", "TestSlowOne", "TestSlowTwo", "example.test/internal/one"} { if !strings.Contains(said, want) { t.Errorf("the verdict does not say %q: %s", want, said) } } if strings.Index(said, "TestSlowOne") > strings.Index(said, "TestSlowTwo") { t.Errorf("the slowest test is not named first: %s", said) } if strings.Contains(said, "TestSlowTwo/sub") { t.Errorf("a subtest is named as if it were a test of its own: %s", said) } } // A unit run within its bound passes and says its count and time. func TestAUnitRunWithinItsBoundPasses(t *testing.T) { said, err := judgeUnitRun(t, recordedUnitRun, "3") if err != nil { t.Fatalf("a unit run of 2.80 s failed a bound of 3 s: %v: %s", err, said) } if !strings.Contains(said, "unit level: 5 tests (1 skipped), 2.80 s (bound 3 s)") { t.Errorf("the level's count and time are not said: %s", said) } }