单元测试基境

概述 #

编写测试代码时,最繁琐的部分之一是将一些 公共的状态变量 设置为某个特定的状态。比如常见的场景:

  • 测试开始时,打开一个数据库连接,测试过程中所有测试用例共享这个连接,测试结束时关闭这个连接
  • 测试开始时,创建一个临时文件,测试过程中所有测试用例共享这个文件句柄,测试结束时关闭并删除这个文件

这种 被共享且状态变化次数很少的值 称为测试的 基境最佳实践是将测试代码中可以复用的部分 放入 基境

TestMain #

TestMain 函数运行在主 goroutine 中 , 可以在调用 m.Run 前后设置 钩子 函数。 如果测试文件中包含 TestMain(*testing.M) 函数, 所有测试方法必须调用参数的 Run 方法触发,如果不调用该方法,直接运行 go test 没有任何效果。 可以利用这一特性, 在 Run 方法执行前后分别挂载 钩子 函数实现 基境 功能。在 TestMain 函数末尾,应该使用 m.Run 的返回值作为参数去调用 os.Exit

示例 #

首先写 4 个数据库的基础操作方法: 创建、更新、读取、删除,这里只是作为 基境 演示,方法内部并不会去实现具体的功能。

CURD 方法 #

将如下代码写入 main.go 文件中:

package main

func create() {
	println("create internal")
}

func update() {
	println("update internal")
}

func get() {
	println("get internal")
}

func delete() {
	println("delete internal")
}

func main() {

}

测试基境 #

将如下代码写入 main_test.go 文件中:

package main

import (
	"os"
	"testing"
)

// 基境初始化操作
func setup() {
	// 模拟数据库建立连接操作
	println("database connected")
}

// 基境释放资源操作
func tearDown() {
	// 模拟数据库断开连接操作
	println("database closed")
}

// 注意参数是 *testing.M, 而非 *testing.T
func TestMain(m *testing.M) {
	setup()
	code := m.Run() // 调用 m.Run() 触发所有 Test_* 测试函数
	tearDown()
	os.Exit(code)
}

func Test_create(t *testing.T) {
	create() // 演示专用,内部不做任何测试
}

func Test_update(t *testing.T) {
	update() // 演示专用,内部不做任何测试
}

func Test_get(t *testing.T) {
	get() // 演示专用,内部不做任何测试
}

func Test_delete(t *testing.T) {
	remove() // 演示专用,内部不做任何测试
}

在上面的代码中,4 个数据库操作函数,因为每个操作都必须持有一个数据库连接对象 (这里只是模拟, 并没有真正去实现代码), 所以这里可以将 数据库的连接和断开两个操作 提取为 基境。 接着将 基境 放入 setuptearDown 两个 钩子 函数, 分别对应数据库的连接和断开操作,最后将两个函数挂载到了 m.Run() 执行的前后,这样就可以自动化运行 基境 操作了。

运行测试 #

$go test -v -count=1 . 
# 输出如下 
database connected
=== RUN   Test_create        
create internal
--- PASS: Test_create (0.00s)
=== RUN   Test_update        
update internal
--- PASS: Test_update (0.00s)
=== RUN   Test_get
get internal
--- PASS: Test_get (0.00s)   
=== RUN   Test_delete        
remove internal
--- PASS: Test_delete (0.00s)
PASS
database closed
ok      helloworld      0.002s

从输出的结果中可以看到,第一行输出了数据库连接操作,最后一行输出了数据库断开连接操作,中间部分是 4 个测试函数。

小结 #

本小节主要介绍了单元测试中 基境 的场景和基本用法,实际开发过程中,基境 的代码不会像示例代码中这么简单,会随着测试代码量的增加而增长, 比较好的实践是: 合理切分包、单个文件的功能和大小,将不同的测试函数进行分类,在这个基础上提取 基境 函数功能

转载申请

本作品采用 知识共享署名 4.0 国际许可协议 进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,商业转载请联系作者获得授权。

© 蛮荆 | 陕公网安备 61011302001681 号 | 陕ICP备2023004378号-1 | Rendered by Hugo