| // Package suite is a simplified version of testify's suite package which has unnecessary dependencies. |
| // Please remove this package whenever possible. |
| package suite |
| |
| import ( |
| "flag" |
| "reflect" |
| "runtime/debug" |
| "strings" |
| "testing" |
| ) |
| |
| // TimeoutFlag is the flag to set a per-test timeout when running tests. Defaults to `-timeout`. |
| var TimeoutFlag = flag.Duration("timeout", 0, "DO NOT USE") |
| |
| var typTestingT = reflect.TypeOf(new(testing.T)) |
| |
| // Run takes a testing suite and runs all of the tests attached to it. |
| func Run(t *testing.T, suite interface{}) { |
| defer failOnPanic(t) |
| |
| suiteSetupDone := false |
| |
| defer func() { |
| if suiteSetupDone { |
| if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok { |
| tearDownAllSuite.TearDownSuite(t) |
| } |
| } |
| }() |
| |
| methodFinder := reflect.TypeOf(suite) |
| for index := 0; index < methodFinder.NumMethod(); index++ { |
| method := methodFinder.Method(index) |
| if !methodFilter(method.Name, method.Type) { |
| continue |
| } |
| t.Run(method.Name, func(t *testing.T) { |
| defer failOnPanic(t) |
| |
| if !suiteSetupDone { |
| if setupAllSuite, ok := suite.(SetupAllSuite); ok { |
| setupAllSuite.SetUpSuite(t) |
| } |
| suiteSetupDone = true |
| } |
| |
| if setupTestSuite, ok := suite.(SetupTestSuite); ok { |
| setupTestSuite.SetUpTest(t) |
| } |
| defer func() { |
| if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok { |
| tearDownTestSuite.TearDownTest(t) |
| } |
| }() |
| |
| method.Func.Call([]reflect.Value{reflect.ValueOf(suite), reflect.ValueOf(t)}) |
| }) |
| } |
| } |
| |
| func failOnPanic(t *testing.T) { |
| r := recover() |
| if r != nil { |
| t.Errorf("test suite panicked: %v\n%s", r, debug.Stack()) |
| t.FailNow() |
| } |
| } |
| |
| func methodFilter(name string, typ reflect.Type) bool { |
| return strings.HasPrefix(name, "Test") && typ.NumIn() == 2 && typ.In(1) == typTestingT // 2 params: method receiver and *testing.T |
| } |