1package suite 2 3import ( 4 "errors" 5 "io/ioutil" 6 "os" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12) 13 14// SuiteRequireTwice is intended to test the usage of suite.Require in two 15// different tests 16type SuiteRequireTwice struct{ Suite } 17 18// TestSuiteRequireTwice checks for regressions of issue #149 where 19// suite.requirements was not initialised in suite.SetT() 20// A regression would result on these tests panicking rather than failing. 21func TestSuiteRequireTwice(t *testing.T) { 22 ok := testing.RunTests( 23 allTestsFilter, 24 []testing.InternalTest{{ 25 Name: "TestSuiteRequireTwice", 26 F: func(t *testing.T) { 27 suite := new(SuiteRequireTwice) 28 Run(t, suite) 29 }, 30 }}, 31 ) 32 assert.Equal(t, false, ok) 33} 34 35func (s *SuiteRequireTwice) TestRequireOne() { 36 r := s.Require() 37 r.Equal(1, 2) 38} 39 40func (s *SuiteRequireTwice) TestRequireTwo() { 41 r := s.Require() 42 r.Equal(1, 2) 43} 44 45type panickingSuite struct { 46 Suite 47 panicInSetupSuite bool 48 panicInSetupTest bool 49 panicInBeforeTest bool 50 panicInTest bool 51 panicInAfterTest bool 52 panicInTearDownTest bool 53 panicInTearDownSuite bool 54} 55 56func (s *panickingSuite) SetupSuite() { 57 if s.panicInSetupSuite { 58 panic("oops in setup suite") 59 } 60} 61 62func (s *panickingSuite) SetupTest() { 63 if s.panicInSetupTest { 64 panic("oops in setup test") 65 } 66} 67 68func (s *panickingSuite) BeforeTest(_, _ string) { 69 if s.panicInBeforeTest { 70 panic("oops in before test") 71 } 72} 73 74func (s *panickingSuite) Test() { 75 if s.panicInTest { 76 panic("oops in test") 77 } 78} 79 80func (s *panickingSuite) AfterTest(_, _ string) { 81 if s.panicInAfterTest { 82 panic("oops in after test") 83 } 84} 85 86func (s *panickingSuite) TearDownTest() { 87 if s.panicInTearDownTest { 88 panic("oops in tear down test") 89 } 90} 91 92func (s *panickingSuite) TearDownSuite() { 93 if s.panicInTearDownSuite { 94 panic("oops in tear down suite") 95 } 96} 97 98func TestSuiteRecoverPanic(t *testing.T) { 99 ok := true 100 panickingTests := []testing.InternalTest{ 101 { 102 Name: "TestPanicInSetupSuite", 103 F: func(t *testing.T) { Run(t, &panickingSuite{panicInSetupSuite: true}) }, 104 }, 105 { 106 Name: "TestPanicInSetupTest", 107 F: func(t *testing.T) { Run(t, &panickingSuite{panicInSetupTest: true}) }, 108 }, 109 { 110 Name: "TestPanicInBeforeTest", 111 F: func(t *testing.T) { Run(t, &panickingSuite{panicInBeforeTest: true}) }, 112 }, 113 { 114 Name: "TestPanicInTest", 115 F: func(t *testing.T) { Run(t, &panickingSuite{panicInTest: true}) }, 116 }, 117 { 118 Name: "TestPanicInAfterTest", 119 F: func(t *testing.T) { Run(t, &panickingSuite{panicInAfterTest: true}) }, 120 }, 121 { 122 Name: "TestPanicInTearDownTest", 123 F: func(t *testing.T) { Run(t, &panickingSuite{panicInTearDownTest: true}) }, 124 }, 125 { 126 Name: "TestPanicInTearDownSuite", 127 F: func(t *testing.T) { Run(t, &panickingSuite{panicInTearDownSuite: true}) }, 128 }, 129 } 130 131 require.NotPanics(t, func() { 132 ok = testing.RunTests(allTestsFilter, panickingTests) 133 }) 134 135 assert.False(t, ok) 136} 137 138// This suite is intended to store values to make sure that only 139// testing-suite-related methods are run. It's also a fully 140// functional example of a testing suite, using setup/teardown methods 141// and a helper method that is ignored by testify. To make this look 142// more like a real world example, all tests in the suite perform some 143// type of assertion. 144type SuiteTester struct { 145 // Include our basic suite logic. 146 Suite 147 148 // Keep counts of how many times each method is run. 149 SetupSuiteRunCount int 150 TearDownSuiteRunCount int 151 SetupTestRunCount int 152 TearDownTestRunCount int 153 TestOneRunCount int 154 TestTwoRunCount int 155 TestSubtestRunCount int 156 NonTestMethodRunCount int 157 158 SuiteNameBefore []string 159 TestNameBefore []string 160 161 SuiteNameAfter []string 162 TestNameAfter []string 163 164 TimeBefore []time.Time 165 TimeAfter []time.Time 166} 167 168type SuiteSkipTester struct { 169 // Include our basic suite logic. 170 Suite 171 172 // Keep counts of how many times each method is run. 173 SetupSuiteRunCount int 174 TearDownSuiteRunCount int 175} 176 177// The SetupSuite method will be run by testify once, at the very 178// start of the testing suite, before any tests are run. 179func (suite *SuiteTester) SetupSuite() { 180 suite.SetupSuiteRunCount++ 181} 182 183func (suite *SuiteTester) BeforeTest(suiteName, testName string) { 184 suite.SuiteNameBefore = append(suite.SuiteNameBefore, suiteName) 185 suite.TestNameBefore = append(suite.TestNameBefore, testName) 186 suite.TimeBefore = append(suite.TimeBefore, time.Now()) 187} 188 189func (suite *SuiteTester) AfterTest(suiteName, testName string) { 190 suite.SuiteNameAfter = append(suite.SuiteNameAfter, suiteName) 191 suite.TestNameAfter = append(suite.TestNameAfter, testName) 192 suite.TimeAfter = append(suite.TimeAfter, time.Now()) 193} 194 195func (suite *SuiteSkipTester) SetupSuite() { 196 suite.SetupSuiteRunCount++ 197 suite.T().Skip() 198} 199 200// The TearDownSuite method will be run by testify once, at the very 201// end of the testing suite, after all tests have been run. 202func (suite *SuiteTester) TearDownSuite() { 203 suite.TearDownSuiteRunCount++ 204} 205 206func (suite *SuiteSkipTester) TearDownSuite() { 207 suite.TearDownSuiteRunCount++ 208} 209 210// The SetupTest method will be run before every test in the suite. 211func (suite *SuiteTester) SetupTest() { 212 suite.SetupTestRunCount++ 213} 214 215// The TearDownTest method will be run after every test in the suite. 216func (suite *SuiteTester) TearDownTest() { 217 suite.TearDownTestRunCount++ 218} 219 220// Every method in a testing suite that begins with "Test" will be run 221// as a test. TestOne is an example of a test. For the purposes of 222// this example, we've included assertions in the tests, since most 223// tests will issue assertions. 224func (suite *SuiteTester) TestOne() { 225 beforeCount := suite.TestOneRunCount 226 suite.TestOneRunCount++ 227 assert.Equal(suite.T(), suite.TestOneRunCount, beforeCount+1) 228 suite.Equal(suite.TestOneRunCount, beforeCount+1) 229} 230 231// TestTwo is another example of a test. 232func (suite *SuiteTester) TestTwo() { 233 beforeCount := suite.TestTwoRunCount 234 suite.TestTwoRunCount++ 235 assert.NotEqual(suite.T(), suite.TestTwoRunCount, beforeCount) 236 suite.NotEqual(suite.TestTwoRunCount, beforeCount) 237} 238 239func (suite *SuiteTester) TestSkip() { 240 suite.T().Skip() 241} 242 243// NonTestMethod does not begin with "Test", so it will not be run by 244// testify as a test in the suite. This is useful for creating helper 245// methods for your tests. 246func (suite *SuiteTester) NonTestMethod() { 247 suite.NonTestMethodRunCount++ 248} 249 250func (suite *SuiteTester) TestSubtest() { 251 suite.TestSubtestRunCount++ 252 253 for _, t := range []struct { 254 testName string 255 }{ 256 {"first"}, 257 {"second"}, 258 } { 259 suiteT := suite.T() 260 suite.Run(t.testName, func() { 261 // We should get a different *testing.T for subtests, so that 262 // go test recognizes them as proper subtests for output formatting 263 // and running individual subtests 264 subTestT := suite.T() 265 suite.NotEqual(subTestT, suiteT) 266 }) 267 suite.Equal(suiteT, suite.T()) 268 } 269} 270 271// TestRunSuite will be run by the 'go test' command, so within it, we 272// can run our suite using the Run(*testing.T, TestingSuite) function. 273func TestRunSuite(t *testing.T) { 274 suiteTester := new(SuiteTester) 275 Run(t, suiteTester) 276 277 // Normally, the test would end here. The following are simply 278 // some assertions to ensure that the Run function is working as 279 // intended - they are not part of the example. 280 281 // The suite was only run once, so the SetupSuite and TearDownSuite 282 // methods should have each been run only once. 283 assert.Equal(t, suiteTester.SetupSuiteRunCount, 1) 284 assert.Equal(t, suiteTester.TearDownSuiteRunCount, 1) 285 286 assert.Equal(t, len(suiteTester.SuiteNameAfter), 4) 287 assert.Equal(t, len(suiteTester.SuiteNameBefore), 4) 288 assert.Equal(t, len(suiteTester.TestNameAfter), 4) 289 assert.Equal(t, len(suiteTester.TestNameBefore), 4) 290 291 assert.Contains(t, suiteTester.TestNameAfter, "TestOne") 292 assert.Contains(t, suiteTester.TestNameAfter, "TestTwo") 293 assert.Contains(t, suiteTester.TestNameAfter, "TestSkip") 294 assert.Contains(t, suiteTester.TestNameAfter, "TestSubtest") 295 296 assert.Contains(t, suiteTester.TestNameBefore, "TestOne") 297 assert.Contains(t, suiteTester.TestNameBefore, "TestTwo") 298 assert.Contains(t, suiteTester.TestNameBefore, "TestSkip") 299 assert.Contains(t, suiteTester.TestNameBefore, "TestSubtest") 300 301 for _, suiteName := range suiteTester.SuiteNameAfter { 302 assert.Equal(t, "SuiteTester", suiteName) 303 } 304 305 for _, suiteName := range suiteTester.SuiteNameBefore { 306 assert.Equal(t, "SuiteTester", suiteName) 307 } 308 309 for _, when := range suiteTester.TimeAfter { 310 assert.False(t, when.IsZero()) 311 } 312 313 for _, when := range suiteTester.TimeBefore { 314 assert.False(t, when.IsZero()) 315 } 316 317 // There are four test methods (TestOne, TestTwo, TestSkip, and TestSubtest), so 318 // the SetupTest and TearDownTest methods (which should be run once for 319 // each test) should have been run four times. 320 assert.Equal(t, suiteTester.SetupTestRunCount, 4) 321 assert.Equal(t, suiteTester.TearDownTestRunCount, 4) 322 323 // Each test should have been run once. 324 assert.Equal(t, suiteTester.TestOneRunCount, 1) 325 assert.Equal(t, suiteTester.TestTwoRunCount, 1) 326 assert.Equal(t, suiteTester.TestSubtestRunCount, 1) 327 328 // Methods that don't match the test method identifier shouldn't 329 // have been run at all. 330 assert.Equal(t, suiteTester.NonTestMethodRunCount, 0) 331 332 suiteSkipTester := new(SuiteSkipTester) 333 Run(t, suiteSkipTester) 334 335 // The suite was only run once, so the SetupSuite and TearDownSuite 336 // methods should have each been run only once, even though SetupSuite 337 // called Skip() 338 assert.Equal(t, suiteSkipTester.SetupSuiteRunCount, 1) 339 assert.Equal(t, suiteSkipTester.TearDownSuiteRunCount, 1) 340 341} 342 343func TestSuiteGetters(t *testing.T) { 344 suite := new(SuiteTester) 345 suite.SetT(t) 346 assert.NotNil(t, suite.Assert()) 347 assert.Equal(t, suite.Assertions, suite.Assert()) 348 assert.NotNil(t, suite.Require()) 349 assert.Equal(t, suite.require, suite.Require()) 350} 351 352type SuiteLoggingTester struct { 353 Suite 354} 355 356func (s *SuiteLoggingTester) TestLoggingPass() { 357 s.T().Log("TESTLOGPASS") 358} 359 360func (s *SuiteLoggingTester) TestLoggingFail() { 361 s.T().Log("TESTLOGFAIL") 362 assert.NotNil(s.T(), nil) // expected to fail 363} 364 365type StdoutCapture struct { 366 oldStdout *os.File 367 readPipe *os.File 368} 369 370func (sc *StdoutCapture) StartCapture() { 371 sc.oldStdout = os.Stdout 372 sc.readPipe, os.Stdout, _ = os.Pipe() 373} 374 375func (sc *StdoutCapture) StopCapture() (string, error) { 376 if sc.oldStdout == nil || sc.readPipe == nil { 377 return "", errors.New("StartCapture not called before StopCapture") 378 } 379 os.Stdout.Close() 380 os.Stdout = sc.oldStdout 381 bytes, err := ioutil.ReadAll(sc.readPipe) 382 if err != nil { 383 return "", err 384 } 385 return string(bytes), nil 386} 387 388func TestSuiteLogging(t *testing.T) { 389 suiteLoggingTester := new(SuiteLoggingTester) 390 capture := StdoutCapture{} 391 internalTest := testing.InternalTest{ 392 Name: "SomeTest", 393 F: func(subT *testing.T) { 394 Run(subT, suiteLoggingTester) 395 }, 396 } 397 capture.StartCapture() 398 testing.RunTests(allTestsFilter, []testing.InternalTest{internalTest}) 399 output, err := capture.StopCapture() 400 require.NoError(t, err, "Got an error trying to capture stdout and stderr!") 401 require.NotEmpty(t, output, "output content must not be empty") 402 403 // Failed tests' output is always printed 404 assert.Contains(t, output, "TESTLOGFAIL") 405 406 if testing.Verbose() { 407 // In verbose mode, output from successful tests is also printed 408 assert.Contains(t, output, "TESTLOGPASS") 409 } else { 410 assert.NotContains(t, output, "TESTLOGPASS") 411 } 412} 413