// Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package testing_test import ( "sync" "testing" ) // The line numbering of this file is important for TestTBHelper. func notHelper(t *testing.T, msg string) { t.Error(msg) } func helper(t *testing.T, msg string) { t.Helper() t.Error(msg) } func notHelperCallingHelper(t *testing.T, msg string) { helper(t, msg) } func helperCallingHelper(t *testing.T, msg string) { t.Helper() helper(t, msg) } func genericHelper[G any](t *testing.T, msg string) { t.Helper() t.Error(msg) } var genericIntHelper = genericHelper[int] func testTestHelper(t *testing.T) { testHelper(t) } func testHelper(t *testing.T) { // Check combinations of directly and indirectly // calling helper functions. notHelper(t, "0") helper(t, "1") notHelperCallingHelper(t, "2") helperCallingHelper(t, "3") // Check a function literal closing over t that uses Helper. fn := func(msg string) { t.Helper() t.Error(msg) } fn("4") t.Run("sub", func(t *testing.T) { helper(t, "5") notHelperCallingHelper(t, "6") // Check that calling Helper from inside a subtest entry function // works as if it were in an ordinary function call. t.Helper() t.Error("7") }) // Check that right caller is reported for func passed to Cleanup when // multiple cleanup functions have been registered. t.Cleanup(func() { t.Helper() t.Error("10") }) t.Cleanup(func() { t.Helper() t.Error("9") }) // Check that helper-ness propagates up through subtests // to helpers above. See https://golang.org/issue/44887. helperSubCallingHelper(t, "11") // Check that helper-ness propagates up through panic/recover. // See https://golang.org/issue/31154. recoverHelper(t, "12") genericHelper[float64](t, "GenericFloat64") genericIntHelper(t, "GenericInt") } func parallelTestHelper(t *testing.T) { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func() { notHelperCallingHelper(t, "parallel") wg.Done() }() } wg.Wait() } func helperSubCallingHelper(t *testing.T, msg string) { t.Helper() t.Run("sub2", func(t *testing.T) { t.Helper() t.Fatal(msg) }) } func recoverHelper(t *testing.T, msg string) { t.Helper() defer func() { t.Helper() if err := recover(); err != nil { t.Errorf("recover %s", err) } }() doPanic(t, msg) } func doPanic(t *testing.T, msg string) { t.Helper() panic(msg) }