Skip to content

rerun-fails: detect parent-test runtime.Goexit as incomplete run - #566

Open
chandler-solo wants to merge 2 commits into
gotestyourself:mainfrom
chandler-solo:chandler/rerunfailssubtestpanicorgoexit
Open

rerun-fails: detect parent-test runtime.Goexit as incomplete run#566
chandler-solo wants to merge 2 commits into
gotestyourself:mainfrom
chandler-solo:chandler/rerunfailssubtestpanicorgoexit

Conversation

@chandler-solo

Copy link
Copy Markdown

Summary

Treat Go's parent-test runtime.Goexit diagnostic as an incomplete test run when using --rerun-fails.

If a subtest calls FailNow/Fatal on a parent *testing.T, Go emits:

test executed panic(nil) or runtime.Goexit: subtest may have called FailNow on a parent test

That can abort the rest of the test branch, so some tests may never run. In that state, rerunning only the observed failed tests is unsafe because gotestsum can report success after the rerun passes while skipped sibling tests were never executed.

Fixes #565

Changes

  • Detect the runtime.Goexit diagnostic alongside existing suspected panic detection.
  • Abort reruns with the existing incomplete-run guard.
  • Add a regression test covering the parent-test runtime.Goexit case.

Testing

go test ./cmd ./testjson
go test ./...

Avoids false green. Reruns only rerun known tests, and such panics
prevent the full list of tests from ever becoming known.

Signed-off-by: David L. Chandler <david.chandler@solo.io>
Signed-off-by: David L. Chandler <david.chandler@solo.io>
@MikeeI

MikeeI commented Aug 7, 2026

Copy link
Copy Markdown

The fix blocks the real parent-Goexit case end to end, but the unanchored fragment match also aborts valid reruns when ordinary test output contains that text.

I reproduced this on Go 1.26.5 with the PR binary. A test that logs the fragment, fails once via a marker file, and passes on rerun behaves as follows:

func TestLoggedText(t *testing.T) {
    t.Log("test executed panic(nil) or runtime.Goexit")
    if _, err := os.Stat("first-run"); err == nil {
        return
    }
    if err := os.WriteFile("first-run", nil, 0o600); err != nil {
        t.Fatal(err)
    }
    t.Fail()
}

With gotestsum v1.13.0, --rerun-fails=1 reruns the test and exits 0. With this PR, the first run is classified as incomplete and gotestsum exits 3 without rerunning:

ERROR rerun aborted because previous run had a suspected panic or runtime.Goexit and some test may not have run
exit=3

The real Go 1.24–1.26 diagnostic includes the complete suffix:

test executed panic(nil) or runtime.Goexit: subtest may have called FailNow on a parent test

and is emitted from testing.go:<line>. Matching the complete diagnostic line, including that suffix and its testing.go: source prefix while allowing the line number to vary, would avoid treating arbitrary user output as an incomplete run.

I also ran the original parent-Goexit scenario against the PR binary: it exits 3 before a rerun and the sibling-test sentinel remains absent, so the intended guard works.

Disclosure

Investigated thoroughly with openai-codex/gpt-5.6-sol (medium reasoning effort), using Oh My Pi as the agent framework.

This report is not generic or unreviewed AI-generated output. Its claims were checked against the cited evidence, and it includes the relevant detail intended to help maintainers resolve the issue.

If reports like this are not useful to the project, please let me know and I will refrain from submitting similar ones. My intent is to help without wasting maintainer time or energy or discouraging their work.

Thank you for your work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gotestsum --rerun-fails can exit successfully after incomplete parent test run

2 participants