suite.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Package suite is a simplified version of testify's suite package which has unnecessary dependencies.
  2. // Please remove this package whenever possible.
  3. package suite
  4. import (
  5. "flag"
  6. "reflect"
  7. "runtime/debug"
  8. "strings"
  9. "testing"
  10. )
  11. // TimeoutFlag is the flag to set a per-test timeout when running tests. Defaults to `-timeout`.
  12. var TimeoutFlag = flag.Duration("timeout", 0, "DO NOT USE")
  13. var typTestingT = reflect.TypeOf(new(testing.T))
  14. // Run takes a testing suite and runs all of the tests attached to it.
  15. func Run(t *testing.T, suite interface{}) {
  16. defer failOnPanic(t)
  17. suiteSetupDone := false
  18. defer func() {
  19. if suiteSetupDone {
  20. if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
  21. tearDownAllSuite.TearDownSuite(t)
  22. }
  23. }
  24. }()
  25. methodFinder := reflect.TypeOf(suite)
  26. suiteName := methodFinder.Elem().Name()
  27. for index := 0; index < methodFinder.NumMethod(); index++ {
  28. method := methodFinder.Method(index)
  29. if !methodFilter(method.Name, method.Type) {
  30. continue
  31. }
  32. t.Run(suiteName+"/"+method.Name, func(t *testing.T) {
  33. defer failOnPanic(t)
  34. if !suiteSetupDone {
  35. if setupAllSuite, ok := suite.(SetupAllSuite); ok {
  36. setupAllSuite.SetUpSuite(t)
  37. }
  38. suiteSetupDone = true
  39. }
  40. if setupTestSuite, ok := suite.(SetupTestSuite); ok {
  41. setupTestSuite.SetUpTest(t)
  42. }
  43. defer func() {
  44. if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok {
  45. tearDownTestSuite.TearDownTest(t)
  46. }
  47. }()
  48. method.Func.Call([]reflect.Value{reflect.ValueOf(suite), reflect.ValueOf(t)})
  49. })
  50. }
  51. }
  52. func failOnPanic(t *testing.T) {
  53. r := recover()
  54. if r != nil {
  55. t.Errorf("test suite panicked: %v\n%s", r, debug.Stack())
  56. t.FailNow()
  57. }
  58. }
  59. func methodFilter(name string, typ reflect.Type) bool {
  60. return strings.HasPrefix(name, "Test") && typ.NumIn() == 2 && typ.In(1) == typTestingT // 2 params: method receiver and *testing.T
  61. }