Go

What are the rules and pitfalls of t.Parallel()?

Question 380MediumGo 1.22 to 1.25
  • Parallel tests in a package run concurrently up to -parallel (default GOMAXPROCS). Packages themselves run in parallel as separate processes (-p).
  • Top-level parallel tests start only after all sequential top-level tests finish.
  • t.Setenv and t.Chdir (1.24) panic if the test or an ancestor called t.Parallel, because env vars and cwd are process-global.
  • Shared mutable state (package vars, global registries like http.DefaultServeMux, time.Now overrides, a single DB schema) causes flaky failures — give each test its own instance.
  • t.Fatal must be called from the test goroutine, not from goroutines the test spawns; use t.Error or send errors back on a channel.
func TestUsers(t *testing.T) {
    t.Parallel()
    db := newTestDB(t) // registers t.Cleanup(db.Close); unique schema per test
    for _, tc := range userCases {
        t.Run(tc.name, func(t *testing.T) {
            t.Parallel()
            ctx := t.Context() // Go 1.24: canceled just before Cleanup runs
            if err := db.CreateUser(ctx, tc.user); (err != nil) != tc.wantErr {
                t.Fatalf("CreateUser(%v) err = %v", tc.user, err)
            }
        })
    }
}

Always combine parallel tests with go test -race; parallelism is how data races in test helpers and production code get exposed.

More on Performance, Profiling & Testing

All 38 Performance, Profiling & Testing questions