setup and teardown for each test using std testing package

Update for Go 1.14 (Q1 2020)

The testing package now supports cleanup functions, called after a test or benchmark has finished, by calling T.Cleanup or B.Cleanup respectively. Example,

func TestFunction(t *testing.T) {
    // setup code
    // sub-tests
    t.Run() 
    t.Run() 
    ...
    // cleanup
    t.Cleanup(func(){
        //tear-down code
    })
}

Here, t.Cleanup runs after the test and all its sub-tests are complete.


Original answer (Feb. 2017)
As shown in the article "Go unit test setup and teardown" from Kare Nuorteva, you could use a setup function which returns... a teardown function to you defer.

See this gist:

func setupSubTest(t *testing.T) func(t *testing.T) {
    t.Log("setup sub test")
    return func(t *testing.T) {
        t.Log("teardown sub test")
    }
}

The setup function is in charge of defining and returning the teardown one.

For each test, for instance in a table-driven test scenario:

for _, tc := range cases {
    t.Run(tc.name, func(t *testing.T) {
        teardownSubTest := setupSubTest(t)
        defer teardownSubTest(t)

        result := Sum(tc.a, tc.b)
        if result != tc.expected {
            t.Fatalf("expected sum %v, but got %v", tc.expected, result)
        }
    })
}

If table driven test pattern works for you, you should stick with it. If you need something more generic and flexible feel free to give https://github.com/houqp/gtest a try.

Here is a quick example:

import (
  "strings"
  "testing"
  "github.com/houqp/gtest"
)

type SampleTests struct{}

// Setup and Teardown are invoked per test group run
func (s *SampleTests) Setup(t *testing.T)      {}
func (s *SampleTests) Teardown(t *testing.T)   {}
// BeforeEach and AfterEach are invoked per test run
func (s *SampleTests) BeforeEach(t *testing.T) {}
func (s *SampleTests) AfterEach(t *testing.T)  {}

func (s *SampleTests) SubTestCompare(t *testing.T) {
  if 1 != 1 {
    t.FailNow()
  }
}

func (s *SampleTests) SubTestCheckPrefix(t *testing.T) {
  if !strings.HasPrefix("abc", "ab") {
    t.FailNow()
  }
}

func TestSampleTests(t *testing.T) {
  gtest.RunSubTests(t, &SampleTests{})
}