Last active
December 24, 2021 03:14
-
-
Save jasonkeene/aee33df73a631b7c1d831fd7b0c581c1 to your computer and use it in GitHub Desktop.
Golang Test Setup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Before method that runs before each test and can communicate values via arguments | |
// Pros: Consolidate setup code | |
// Pros: No sharing of memory between tests, can run in parallel | |
// Pros: Use symbols for dependencies | |
// Cons: A little bit magical with using reflection. | |
func TestSomething(t *testing.T) { | |
t.Before(func (t *testing.T) (*db.Conn, map[string]interface{}) { | |
return createDBConn(t), createFixture() | |
}) | |
t.Run("some create test", func (t *testing.T, dbConn *db.Conn, fixture map[string]interface{}) { | |
dbConn.Create(fixture) | |
}) | |
t.Run("some update test", func (t *testing.T, dbConn *db.Conn, fixture map[string]interface{}) { | |
dbConn.Update(fixture) | |
}) | |
t.Run("some delete test", func (t *testing.T, dbConn *db.Conn, fixture map[string]interface{}) { | |
dbConn.Update(fixture) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Before method that runs before each test and can communicate values to the test through state on T | |
// Pros: Consolidate setup code | |
// Pros: No sharing of memory between tests, can run in parallel | |
// Cons: Does not use symbols for dependencies | |
// Cons: Requires type asserting | |
func TestSomething(t *testing.T) { | |
t.Before(func (t *testing.T) { | |
t.S("dbConn", createDBConn(t)) | |
t.S("fixture", createFixture()) | |
}) | |
t.Run("some create test", func (t *testing.T) { | |
t.L("dbConn").(*db.Conn).Create(t.L("fixture").(map[string]interface{})) | |
}) | |
t.Run("some update test", func (t *testing.T) { | |
t.L("dbConn").(*db.Conn).Update(t.L("fixture").(map[string]interface{})) | |
}) | |
t.Run("some delete test", func (t *testing.T) { | |
t.L("dbConn").(*db.Conn).Update(t.L("fixture").(map[string]interface{})) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A setup func that mutates closure variables | |
// Pros: Use symbols for dependencies | |
// Pros: Consolidate setup code | |
// Cons: Repeat `setup()` call in each test | |
// Cons: Closure variables share memory between tests which prevents running in parallel | |
func TestSomething(t *testing.T) { | |
var ( | |
dbConn *db.Conn | |
fixture map[string]interface{} | |
) | |
setup := func () { | |
dbConn = createDBConn(t) | |
fixture = createFixture() | |
} | |
t.Run("some create test", func (t *testing.T) { | |
setup() | |
dbConn.Create(fixture) | |
}) | |
t.Run("some update test", func (t *testing.T) { | |
setup() | |
dbConn.Update(fixture) | |
}) | |
t.Run("some delete test", func (t *testing.T) { | |
setup() | |
dbConn.Delete(fixture) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Have all setup code invoked from each test | |
// Pros: No sharing of memory between tests, can run in parallel | |
// Pros: Use symbols for dependencies | |
// Cons: Repeat setup code in each test | |
func TestSomething(t *testing.T) { | |
t.Run("some create test", func (t *testing.T) { | |
dbConn := createDBConn(t) | |
fixture := createFixture() | |
dbConn.Create(fixture) | |
}) | |
t.Run("some update test", func (t *testing.T) { | |
dbConn := createDBConn(t) | |
fixture := createFixture() | |
dbConn.Update(fixture) | |
}) | |
t.Run("some delete test", func (t *testing.T) { | |
dbConn := createDBConn(t) | |
fixture := createFixture() | |
dbConn.Delete(fixture) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Table tests can be used to reduce setup boilerplate | |
// Pros: Consolidate setup code | |
// Pros: No sharing of memory between tests, can run in parallel | |
// Pros: Use symbols for dependencies | |
// Cons: Tests become generic and hard to understand | |
func TestSomething(t *testing.T) { | |
testBodies := map[string]func(dbConn *db.Conn, fixture map[string]interface{}){ | |
"create": func(dbConn *db.Conn, fixture map[string]interface{}) { | |
dbConn.Create(fixture) | |
}, | |
"update": func(dbConn *db.Conn, fixture map[string]interface{}) { | |
dbConn.Update(fixture) | |
}, | |
"delete": func(dbConn *db.Conn, fixture map[string]interface{}) { | |
dbConn.Update(fixture) | |
}, | |
} | |
for tn, tb := range testBodies { | |
dbConn := createDBConn(t) | |
fixture := createFixture() | |
t.Run(fmt.Sprintf("some %s test", tn), func (t *testing.T) { | |
tb(dbConn, fixture) | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment