From a4c24896e39914dec5ed4fb949ee80700eb06592 Mon Sep 17 00:00:00 2001 From: Sam Nelson Date: Mon, 14 Oct 2013 15:13:28 -0600 Subject: [PATCH] Initial buildup/teardown functionality for issue 19 --- suite/doc.go | 6 ++++ suite/interfaces.go | 34 ++++++++++++++++++++++ suite/suite.go | 51 ++++++++++++++++++++++++++++++++ suite/suite_test.go | 71 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 suite/doc.go create mode 100644 suite/interfaces.go create mode 100644 suite/suite.go create mode 100644 suite/suite_test.go diff --git a/suite/doc.go b/suite/doc.go new file mode 100644 index 0000000..b915d17 --- /dev/null +++ b/suite/doc.go @@ -0,0 +1,6 @@ +// A full testing suite, to expand upon the features of Go's built-in +// testing tool. Most importantly, this package provides interfaces +// and structs for creating suites of related tests, and putting +// related functionality into methods that will be run before and/or +// after the whole suite or each individual test. +package suite diff --git a/suite/interfaces.go b/suite/interfaces.go new file mode 100644 index 0000000..55d0977 --- /dev/null +++ b/suite/interfaces.go @@ -0,0 +1,34 @@ +package suite + +import "testing" + +// TestingSuite can store and return the current *testing.T context +// generated by 'go test'. +type TestingSuite interface { + T() *testing.T + SetT(*testing.T) +} + +// BeforeAllSuite has a BeforeSuite method, intended to be run before +// the entire suite is tested. +type BeforeAllSuite interface { + BeforeSuite() +} + +// BeforeTestSuite has a BeforeTest method, intended to be run before +// each test. +type BeforeTestSuite interface { + BeforeTest() +} + +// AfterAllSuite has an AfterSuite method, intended to be run after the +// entire suite has been tested. +type AfterAllSuite interface { + AfterSuite() +} + +// AfterTestSuite has an AfterTest method, intended to be run after +// each test. +type AfterTestSuite interface { + AfterTest() +} diff --git a/suite/suite.go b/suite/suite.go new file mode 100644 index 0000000..d37ad96 --- /dev/null +++ b/suite/suite.go @@ -0,0 +1,51 @@ +package suite + +import ( + "testing" + "reflect" + "regexp" +) + +// Suite is a basic testing suite with methods for storing and +// retrieving the current *testing.T context. +type Suite struct { + t *testing.T +} + +// T retrieves the current *testing.T context. +func (suite *Suite) T() *testing.T { + return suite.t +} + +// SetT sets the current *testing.T context. +func (suite *Suite) SetT(t *testing.T) { + suite.t = t +} + +// Run takes a testing suite and runs all of the tests attached +// to it. +func Run(t *testing.T, suite TestingSuite) { + suite.SetT(t) + + if beforeAllSuite, ok := suite.(BeforeAllSuite); ok { + beforeAllSuite.BeforeSuite() + } + + if afterAllSuite, ok := suite.(AfterAllSuite); ok { + defer afterAllSuite.AfterSuite() + } + + methodFinder := reflect.TypeOf(suite) + for index := 0; index < methodFinder.NumMethod(); index++ { + method := methodFinder.Method(index) + if ok, _ := regexp.MatchString("^Test", method.Name); ok { + if beforeTestSuite, ok := suite.(BeforeTestSuite); ok { + beforeTestSuite.BeforeTest() + } + method.Func.Call([]reflect.Value{reflect.ValueOf(suite)}) + if afterTestSuite, ok := suite.(AfterTestSuite); ok { + afterTestSuite.AfterTest() + } + } + } +} diff --git a/suite/suite_test.go b/suite/suite_test.go new file mode 100644 index 0000000..5275c46 --- /dev/null +++ b/suite/suite_test.go @@ -0,0 +1,71 @@ +package suite + +import ( + "testing" + "github.com/stretchr/testify/assert" +) + +// This suite is intended to store values to make sure that only +// testing-suite-related methods are run. +type SuiteTester struct { + Suite + BeforeSuiteRunCount int + AfterSuiteRunCount int + BeforeTestRunCount int + AfterTestRunCount int + TestOneRunCount int + TestTwoRunCount int + NonTestMethodRunCount int +} + +func (suite *SuiteTester) BeforeSuite() { + suite.BeforeSuiteRunCount++ +} + +func (suite *SuiteTester) AfterSuite() { + suite.AfterSuiteRunCount++ +} + +func (suite *SuiteTester) BeforeTest() { + suite.BeforeTestRunCount++ +} + +func (suite *SuiteTester) AfterTest() { + suite.AfterTestRunCount++ +} + +func (suite *SuiteTester) TestOne() { + suite.TestOneRunCount++ +} + +func (suite *SuiteTester) TestTwo() { + suite.TestTwoRunCount++ +} + +func (suite *SuiteTester) NonTestMethod() { + suite.NonTestMethodRunCount++ +} + +func TestSuiteLogic(t *testing.T) { + suiteTester := new(SuiteTester) + Run(t, suiteTester) + + // The suite was only run once, so the BeforeSuite and AfterSuite + // methods should have each been run only once. + assert.Equal(t, suiteTester.BeforeSuiteRunCount, 1) + assert.Equal(t, suiteTester.AfterSuiteRunCount, 1) + + // There are two test methods (TestOne and TestTwo), so the + // BeforeTest and AfterTest methods (which should be run once for + // each test) should have been run twice. + assert.Equal(t, suiteTester.BeforeTestRunCount, 2) + assert.Equal(t, suiteTester.AfterTestRunCount, 2) + + // Each test should have been run once. + assert.Equal(t, suiteTester.TestOneRunCount, 1) + assert.Equal(t, suiteTester.TestTwoRunCount, 1) + + // Methods that don't match the test method identifier shouldn't + // have been run at all. + assert.Equal(t, suiteTester.NonTestMethodRunCount, 0) +}