notexOPENOverview
Notex/Languages/Setting Up and Tearing Down
05.05LESSON 05 OF 29 · 2 MIN READ

Setting Up and Tearing Down

Always free to read

Sometimes you have some common state that you want to set up before any tests run and remove when testing is complete. Use a TestMain function to manage this state and run your tests:

var testTime time.Time

func TestMain(m *testing.M) {
    fmt.Println("Set up stuff for tests here")
    testTime = time.Now()
    exitVal := m.Run()
    fmt.Println("Clean up stuff after tests here")
    os.Exit(exitVal)
}

func TestFirst(t *testing.T) {
    slog.Info("TestFirst uses stuff set up in TestMain", testTime)
}

func TestSecond(t *testing.T) {
    slog.Info("TestSecond also uses stuff set up in TestMain", testTime)
}

Both TestFirst and TestSecond refer to the package-level variable testTime. Assume that it needs to be initialized in order for the tests to run properly. You declare a function called TestMain with a parameter of type *testing.M. If there’s a function named TestMain in a package, go test calls it instead of the test functions. It is the responsibility of the TestMain function to set up any state that’s necessary to make the tests in the package run correctly.

Once the state is configured, the TestMain function calls the Run method on *testing.M. This runs the test functions in the package. The Run method returns the exit code; 0 indicates that all tests passed. Finally, the TestMain function must call os.Exit with the exit code returned from Run.

Running go test on this produces the output:

$ go test
Set up stuff for tests here
TestFirst uses stuff set up in TestMain 2026-03-30 23:10:55.190364 -0400 EDT
    m=+0.000474084
TestSecond also uses stuff set up in TestMain 2026-03-30 23:10:55.190364 -0400
    EDT m=+0.000474084
PASS
Clean up stuff after tests here
ok      test_examples/testmain  0.006s

Note

Be aware that TestMain is invoked once, not before and after each individual test. You can have only one TestMain per package.

TestMain is useful in two common situations:

  • When you need to set up data in an external repository, such as a database

  • When the code being tested depends on package-level variables that need to be initialized

As I’ve mentioned before (and will again!), you should avoid package-level variables in your programs. They make it hard to understand how data flows through your program. If you are using TestMain for this reason, consider refactoring your code.

Progress is saved on this device.
KEEP EXPLORING

One note leads to another.

Back to the library →
⌕
Search across the entire library ⌘ K