suite.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package suite
  2. import (
  3. "flag"
  4. "fmt"
  5. "os"
  6. "reflect"
  7. "regexp"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/stretchr/testify/require"
  11. )
  12. var matchMethod = flag.String("testify.m", "", "regular expression to select tests of the testify suite to run")
  13. // Suite is a basic testing suite with methods for storing and
  14. // retrieving the current *testing.T context.
  15. type Suite struct {
  16. *assert.Assertions
  17. require *require.Assertions
  18. t *testing.T
  19. }
  20. // T retrieves the current *testing.T context.
  21. func (suite *Suite) T() *testing.T {
  22. return suite.t
  23. }
  24. // SetT sets the current *testing.T context.
  25. func (suite *Suite) SetT(t *testing.T) {
  26. suite.t = t
  27. suite.Assertions = assert.New(t)
  28. suite.require = require.New(t)
  29. }
  30. // Require returns a require context for suite.
  31. func (suite *Suite) Require() *require.Assertions {
  32. if suite.require == nil {
  33. suite.require = require.New(suite.T())
  34. }
  35. return suite.require
  36. }
  37. // Assert returns an assert context for suite. Normally, you can call
  38. // `suite.NoError(expected, actual)`, but for situations where the embedded
  39. // methods are overridden (for example, you might want to override
  40. // assert.Assertions with require.Assertions), this method is provided so you
  41. // can call `suite.Assert().NoError()`.
  42. func (suite *Suite) Assert() *assert.Assertions {
  43. if suite.Assertions == nil {
  44. suite.Assertions = assert.New(suite.T())
  45. }
  46. return suite.Assertions
  47. }
  48. // Run takes a testing suite and runs all of the tests attached
  49. // to it.
  50. func Run(t *testing.T, suite TestingSuite) {
  51. suite.SetT(t)
  52. if setupAllSuite, ok := suite.(SetupAllSuite); ok {
  53. setupAllSuite.SetupSuite()
  54. }
  55. defer func() {
  56. if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
  57. tearDownAllSuite.TearDownSuite()
  58. }
  59. }()
  60. methodFinder := reflect.TypeOf(suite)
  61. tests := []testing.InternalTest{}
  62. for index := 0; index < methodFinder.NumMethod(); index++ {
  63. method := methodFinder.Method(index)
  64. ok, err := methodFilter(method.Name)
  65. if err != nil {
  66. fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err)
  67. os.Exit(1)
  68. }
  69. if ok {
  70. test := testing.InternalTest{
  71. Name: method.Name,
  72. F: func(t *testing.T) {
  73. parentT := suite.T()
  74. suite.SetT(t)
  75. if setupTestSuite, ok := suite.(SetupTestSuite); ok {
  76. setupTestSuite.SetupTest()
  77. }
  78. if beforeTestSuite, ok := suite.(BeforeTest); ok {
  79. beforeTestSuite.BeforeTest(methodFinder.Elem().Name(), method.Name)
  80. }
  81. defer func() {
  82. if afterTestSuite, ok := suite.(AfterTest); ok {
  83. afterTestSuite.AfterTest(methodFinder.Elem().Name(), method.Name)
  84. }
  85. if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok {
  86. tearDownTestSuite.TearDownTest()
  87. }
  88. suite.SetT(parentT)
  89. }()
  90. method.Func.Call([]reflect.Value{reflect.ValueOf(suite)})
  91. },
  92. }
  93. tests = append(tests, test)
  94. }
  95. }
  96. if !testing.RunTests(func(_, _ string) (bool, error) { return true, nil },
  97. tests) {
  98. t.Fail()
  99. }
  100. }
  101. // Filtering method according to set regular expression
  102. // specified command-line argument -m
  103. func methodFilter(name string) (bool, error) {
  104. if ok, _ := regexp.MatchString("^Test", name); !ok {
  105. return false, nil
  106. }
  107. return regexp.MatchString(*matchMethod, name)
  108. }