Setup and teardown unittests in golang

Setup and teardown unittests in golang

Right now we had a lot of discussions about golang in our team. My colleague Andreas complained about the unit testing especially setting them up and using teardown functions. I didn’t add and problem with it until now, but he activated my mind and I searched for sultions for it. While searching I found setup-and-teardown-unit-test-in-go which brought me up to slidely different solution. Basically this is now what I found:

I basically setup a simple project. The code is just the following

main.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import "fmt"

func main() {
	fmt.Println(multiply(3, 3))
}

func multiply(number1, number2 int) int {
	return number1 * number2
}

Also I setup a simple test for it. The idea of the teardown is basically to create function which setups the tests and at the same time returns a function for the teardown. Then I can just register the handler via t.Cleanup.

main_test.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
	"log"
	"testing"

	"github.com/stretchr/testify/assert"
)

func setupTest(t *testing.T) func() {
	log.Println("Setup Test")
	return func() {
		log.Println("Teardown Test")
	}
}

func TestMultiply(t *testing.T) {
	t.Cleanup(setupTest(t))

	log.Println("Testing now Multiply")
	res := multiply(3, 3)
	assert.Equal(t, 9, res)
}

The output of this looks like:

go test
2022/03/29 17:54:18 Setup Test
2022/03/29 17:54:18 Testing now Multiply
2022/03/29 17:54:18 Teardown Test
PASS
ok      github.com/steffakasid/unittest 1.426s

I also like the other possibilities of testing.T to setup unittests:

UPDATE 04.04.2022:

I came up that there are multiple/ different ways on how to setup unittests. The mentioned Method above works pretty well on subtests using t.Run even if you could use this as well on any other test function which has an instance of *testing.T. Another approach to use setup and teardown code would be:

Simple test function setup and teardown
1
2
3
4
5
6
7
8
9
func TestSomething(t *testing.T) {
    // Put setup code here

    t.Run("Some Test", func(t *testing.T) {
        // Tests goes here
    })

    // Teardown code here
}

Or you can even setup your package tests using func MainTest:

MainTest
1
2
3
4
5
6
7
func TestMain(m *testing.M) {
    // Put setup code here

    m.Run()

    // Teardown code here
}

TestMain will just trigger that the test functions are not called directly instead TestMain is executed. The call to m.Run() will then execute all test functions.

This can also be found here.

Update 25.04.2022

I just found something interesing on how to seperate tests using build tags: Separate Your Go Tests with Build Tags