相信大家在写测试时,都会需要启动而外服务,像是 Redis 或 Postgres 等,而开始测试前会需要初始化链接,或者是准备测试资料,测试结束后就关闭链接,并且移除不必要的链接。在 Go 语言内开发者不用去依赖第三方的套件,透过内建的 TestMain 就可以非常轻松完成此事情。
TestMain
Go 语言在测试套件内直接提供了 TestMain 函式,功能就是让开发者可以在开始测试前准备环境 (setup) 或是测试结束后移除环境 (teardown)。看看正常执行范例。
func TestMain(m *testing.M) {
// call flag.Parse() here if TestMain uses flags
os.Exit(m.Run())
}
接着可以新增 setup() 及 teardown() 函数
func setup() {
// Do something here.
fmt.Printf("\033[1;33m%s\033[0m", "> Setup completed\n")
}
func teardown() {
// Do something here.
fmt.Printf("\033[1;33m%s\033[0m", "> Teardown completed")
fmt.Printf("\n")
}
func TestMain(m *testing.M) {
setup()
code := m.Run()
teardown()
os.Exit(code)
}
执行 go test -v . 后可以看到结果
这是符合我们的需求,可以在任何测试前准备环境,结束后可以清理相关环境
整合 TestMain + Teardown
我们来将上述的案例整合一起使用,先写一个简单的 ToString 功能
package foobar
import "fmt"
// ToString convert any type to string
func ToString(value interface{}) string {
if v, ok := value.(*string); ok {
return *v
}
return fmt.Sprintf("%v", value)
}
接着写测试
package foobar
import (
"fmt"
"os"
"reflect"
"testing"
)
func setup() {
// Do something here.
fmt.Printf("\033[1;33m%s\033[0m", "> Setup completed\n")
}
func teardown() {
// Do something here.
fmt.Printf("\033[1;33m%s\033[0m", "> Teardown completed")
fmt.Printf("\n")
}
func TestMain(m *testing.M) {
setup()
code := m.Run()
teardown()
os.Exit(code)
}
func setupTest(tb testing.TB) func(tb testing.TB) {
fmt.Printf("\033[1;34m%s\033[0m", ">> Setup Test\n")
return func(tb testing.TB) {
fmt.Printf("\033[1;34m%s\033[0m", ">> Teardown Test\n")
}
}
func TestToString(t *testing.T) {
type args struct {
value interface{}
}
tests := []struct {
name string
args args
want interface{}
}{
{
name: "int",
args: args{
value: 101,
},
want: "101",
},
{
name: "int64",
args: args{
value: int64(100),
},
want: "100",
},
{
name: "boolean",
args: args{
value: true,
},
want: "true",
},
{
name: "float32",
args: args{
value: float32(23.03),
},
want: "23.03",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
teardown := setupTest(t)
defer teardown(t)
if got := ToString(tt.args.value); !reflect.DeepEqual(got, tt.want) {
t.Errorf("ToString() = %v, want %v", got, tt.want)
}
})
}
}
最后结果如下
原文:https://blog.wu-boy.com/2022/07/setup-and-teardown-with-unit-testing-in-golang/