Skip to content

Instantly share code, notes, and snippets.

@benjaminjkraft
Last active July 24, 2019 21:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benjaminjkraft/32d8327e115f4991354c498219772525 to your computer and use it in GitHub Desktop.
Save benjaminjkraft/32d8327e115f4991354c498219772525 to your computer and use it in GitHub Desktop.
Go testing POCs
package sandbox
import (
"testing"
"github.com/stretchr/testify/assert"
)
// WithSetup would be a standard util. It accepts a setup func (which returns
// a teardown func to undo its work) and the test itself.
func WithSetup(setup func(*testing.T) func(*testing.T), test func(*testing.T)) func(*testing.T) {
return func(t *testing.T) {
teardown := setup(t)
test(t)
teardown(t)
}
}
func TestFoo(t *testing.T) {
a := 1
setup := func(t *testing.T) func(t *testing.T) {
oldA := a
a = 2
return func(t *testing.T) {
a = oldA
}
}
t.Run("no setup", func(t *testing.T) {
assert.Equal(t, 1, a)
a = 3 // make a mess
})
t.Run("setup 1", WithSetup(setup, func(t *testing.T) {
assert.Equal(t, 2, a)
a = 6
}))
t.Run("setup 2", WithSetup(setup, func(t *testing.T) {
assert.Equal(t, 2, a)
a = 7
}))
t.Run("no setup 2", func(t *testing.T) {
assert.Equal(t, 3, a)
})
}
package sandbox
import (
"testing"
"github.com/stretchr/testify/assert"
)
// This would all be standard utilities
type testCase struct {
name string
cleanup []func(*Suite)
}
type Suite struct {
t *testing.T
setup []func(*Suite)
teardown []func(*Suite)
currentCase *testCase
}
func NewSuite(t *testing.T) *Suite {
return &Suite{t: t}
}
// Run can be used like testing.T.Run.
func (s *Suite) Run(name string, test func(*Suite)) bool {
return s.t.Run(name, func(t *testing.T) {
s.currentCase = &testCase{name: name}
for _, setup := range s.setup {
setup(s)
}
test(s)
for _, cleanup := range s.currentCase.cleanup {
cleanup(s)
}
for _, teardown := range s.teardown {
teardown(s)
}
})
}
// AddSetup runs the given function at the beginning of each case.
func (s *Suite) AddSetup(setup func(*Suite)) {
s.setup = append(s.setup, setup)
}
// AddTeardown runs the given function at the end of each case.
func (s *Suite) AddTeardown(teardown func(*Suite)) {
s.teardown = append(s.teardown, teardown)
}
// AddCleanup runs the given function at the end of this test (useful for
// calling within a setup function which wants to undo its own work).
func (s *Suite) AddCleanup(cleanup func(*Suite)) {
s.currentCase.cleanup = append(s.currentCase.cleanup, cleanup)
}
// Here's what a test would look like.
func TestBar(t *testing.T) {
b := 1
s := NewSuite(t)
// one could also call s.AddSetup(testutil.SetupDB) to incorporate a
// standard fixture setup.
s.AddSetup(func(s *Suite) {
oldB := b
b = 2
s.AddCleanup(func(s *Suite) {
b = oldB
})
})
// once-per-suite setup can just go inline here
s.Run("case 1", func(s *Suite) {
assert.Equal(t, 2, b)
b = 3 // make a mess
})
s.Run("case 2", func(s *Suite) {
assert.Equal(t, 2, b)
b = 3
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment