mirror of https://github.com/stretchr/testify.git
Add stats to suites and tests
parent
cb23521296
commit
e8910bb335
|
@ -1,6 +1,8 @@
|
|||
package suite
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestingSuite can store and return the current *testing.T context
|
||||
// generated by 'go test'.
|
||||
|
@ -44,3 +46,8 @@ type BeforeTest interface {
|
|||
type AfterTest interface {
|
||||
AfterTest(suiteName, testName string)
|
||||
}
|
||||
|
||||
// WithStats is a suite which measures some stats for its tests.
|
||||
type WithStats interface {
|
||||
HandleStats(suiteName string, stats *SuiteInformation)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package suite
|
||||
|
||||
import "time"
|
||||
|
||||
// SuiteInformation stats stores stats for the whole suite execution.
|
||||
type SuiteInformation struct {
|
||||
Start, End time.Time
|
||||
Passed bool
|
||||
TestStats map[string]*TestInformation
|
||||
}
|
||||
|
||||
// TestInformation stores information about the execution of each test.
|
||||
type TestInformation struct {
|
||||
TestName string
|
||||
Start, End time.Time
|
||||
Passed bool
|
||||
}
|
||||
|
||||
func newSuiteInformation() *SuiteInformation {
|
||||
testStats := make(map[string]*TestInformation)
|
||||
|
||||
return &SuiteInformation{
|
||||
TestStats: testStats,
|
||||
Passed: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (s SuiteInformation) start(testName string) {
|
||||
s.TestStats[testName] = &TestInformation{
|
||||
TestName: testName,
|
||||
Start: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s SuiteInformation) end(testName string, passed bool) {
|
||||
s.TestStats[testName].End = time.Now()
|
||||
s.TestStats[testName].Passed = passed
|
||||
}
|
|
@ -9,6 +9,7 @@ import (
|
|||
"runtime/debug"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -87,6 +88,14 @@ func Run(t *testing.T, suite TestingSuite) {
|
|||
|
||||
suiteSetupDone := false
|
||||
|
||||
var (
|
||||
stats *SuiteInformation
|
||||
)
|
||||
|
||||
if _, measureStats := suite.(WithStats); measureStats {
|
||||
stats = newSuiteInformation()
|
||||
}
|
||||
|
||||
methodFinder := reflect.TypeOf(suite)
|
||||
tests := []testing.InternalTest{}
|
||||
for index := 0; index < methodFinder.NumMethod(); index++ {
|
||||
|
@ -96,21 +105,36 @@ func Run(t *testing.T, suite TestingSuite) {
|
|||
fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
suiteName := methodFinder.Elem().Name()
|
||||
|
||||
if !suiteSetupDone {
|
||||
if stats != nil {
|
||||
stats.Start = time.Now()
|
||||
}
|
||||
|
||||
if setupAllSuite, ok := suite.(SetupAllSuite); ok {
|
||||
setupAllSuite.SetupSuite()
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
|
||||
testsSync.Wait()
|
||||
tearDownAllSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
if suiteWithStats, measureStats := suite.(WithStats); measureStats {
|
||||
stats.End = time.Now()
|
||||
suiteWithStats.HandleStats(suiteName, stats)
|
||||
}
|
||||
}()
|
||||
suiteSetupDone = true
|
||||
}
|
||||
|
||||
test := testing.InternalTest{
|
||||
Name: method.Name,
|
||||
F: func(t *testing.T) {
|
||||
|
@ -122,16 +146,34 @@ func Run(t *testing.T, suite TestingSuite) {
|
|||
if setupTestSuite, ok := suite.(SetupTestSuite); ok {
|
||||
setupTestSuite.SetupTest()
|
||||
}
|
||||
|
||||
if beforeTestSuite, ok := suite.(BeforeTest); ok {
|
||||
beforeTestSuite.BeforeTest(methodFinder.Elem().Name(), method.Name)
|
||||
}
|
||||
|
||||
if stats != nil {
|
||||
stats.start(method.Name)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if afterTestSuite, ok := suite.(AfterTest); ok {
|
||||
afterTestSuite.AfterTest(methodFinder.Elem().Name(), method.Name)
|
||||
if stats != nil {
|
||||
passed := !t.Failed()
|
||||
|
||||
stats.end(method.Name, passed)
|
||||
|
||||
if !passed {
|
||||
stats.Passed = false
|
||||
}
|
||||
}
|
||||
|
||||
if afterTestSuite, ok := suite.(AfterTest); ok {
|
||||
afterTestSuite.AfterTest(suiteName, method.Name)
|
||||
}
|
||||
|
||||
if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok {
|
||||
tearDownTestSuite.TearDownTest()
|
||||
}
|
||||
|
||||
suite.SetT(parentT)
|
||||
}()
|
||||
method.Func.Call([]reflect.Value{reflect.ValueOf(suite)})
|
||||
|
|
|
@ -482,3 +482,33 @@ func (s *CallOrderSuite) Test_A() {
|
|||
func (s *CallOrderSuite) Test_B() {
|
||||
s.call("Test B")
|
||||
}
|
||||
|
||||
type suiteWithStats struct {
|
||||
Suite
|
||||
wasCalled bool
|
||||
stats *SuiteInformation
|
||||
}
|
||||
|
||||
func (s *suiteWithStats) HandleStats(suiteName string, stats *SuiteInformation) {
|
||||
s.wasCalled = true
|
||||
s.stats = stats
|
||||
}
|
||||
|
||||
func (s *suiteWithStats) TestSomething() {
|
||||
s.Equal(1, 1)
|
||||
}
|
||||
|
||||
func TestSuiteWithStats(t *testing.T) {
|
||||
suiteWithStats := new(suiteWithStats)
|
||||
Run(t, suiteWithStats)
|
||||
|
||||
assert.True(t, suiteWithStats.wasCalled)
|
||||
assert.NotZero(t, suiteWithStats.stats.Start)
|
||||
assert.NotZero(t, suiteWithStats.stats.End)
|
||||
assert.True(t, suiteWithStats.stats.Passed)
|
||||
|
||||
testStats := suiteWithStats.stats.TestStats["TestSomething"]
|
||||
assert.NotZero(t, testStats.Start)
|
||||
assert.NotZero(t, testStats.End)
|
||||
assert.True(t, testStats.Passed)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue