go test单元测试详解

目录

介绍&测试范围

测试函数

执行机制

常用执行模式

子测试

帮助函数Helper()

测试覆盖率


介绍&测试范围

go test测试是go自带的测试工具,主要包括单元测试和性能测试两大类。

包括了工程目录下所有以_test.go为后缀名的源代码文件,这些文件在编译时不会被编译到最终的可执行文件中。

测试函数

命名

一般是以Test开头再加自定义函数名

正常:TestAnd

错误:Testand

参数

测试函数参数只有一个,普通的单元测试均为*testing.T,参数如果不对则会提示:Wrong test signature

可允许的参数类型如:

*testing.T:普通单元测试

*testing.B:benchmark基准测试,一般用于测试性能

*testing.M:测试主函数,在运行指定测试函数之前首先运行测试文件中的func TestMain(m *testing.M),TestMain运行在主goroutine中。

如待测函数为Add:

Go 复制代码
func Add(a int, b int) int {
    return a + b
}

Go 复制代码
func TestAdd(t *testing.T) {
    if result := Add(1, 2); result != 3 {
        t.Errorf("1 + 2 = 3, not %d", result)
    }

    if result := Add(-1, -2); result != -3 {
        t.Errorf("-1 + -2 = -3, not %d", result)
    }
}

执行机制

go test过程首先扫描*_test.go的文件,会生成一个临时的main包用于调用相应的测试函数,然后构建、运行、产生测试结果,最后清理测试中生成的临时文件。

常用执行模式

1、仅运行一个测试函数

Go 复制代码
go test -run TestAdd

2、运行一个包下所有的测试函数

根目录下运行指定包

Go 复制代码
go test awesomeProject/testt 

或进入指定包下再执行

Go 复制代码
go test -v

其中 -v用于显示具体用例测试结果,不是必须的

注意,当有两个测试函数 TestAdd、TestAdd0时,执行go test -run TestAdd会将这两个都进行测试。

测试打印

测试函数与其它go函数一样都是函数,可使用fmt、log等进行打印,但参数t自带了常用的打印方法:

Go 复制代码
    // 打印日志
    t.Log()
    t.Logf()
    
    // 打印错误,遇到错误终止执行
    t.Fatal()
    t.Fatalf()
    
    // 打印错误,遇到错误继续执行
    t.Error()
    t.Errorf()

子测试

子测试是指在测试场景下允许使用t.Run来创建不同的子测试用例。

举例如下:

Go 复制代码
func TestAdd(t *testing.T) {
    testsAdd := []struct {
        a, b int
        want int
    }{
        {0, 1, 1},
        {1, 2, 3},
        {2, 2, 4},
        {0, -1, -1},
        {-3, 4, 1},
        {-3, 1, -2},
        {-1, -1, -2},
        {-1, -2, -3},
    }

    for _, tt := range testsAdd {
        t.Run("", func(t *testing.T) {
            if got := Add(tt.a, tt.b); got != tt.want {
                t.Errorf("Add(%d,%d) = %d, want %d", tt.a, tt.b, got, tt.want)
            }
        })
    }
}

这种写法直观、清晰,新增用例方便、格式统一。用例正常时结果如下:

Go 复制代码
PASS
ok      awesomeProject/testt    0.754s

若将第一个用例写错模拟Add函数问题,结果如下:

Go 复制代码
--- FAIL: TestAdd (0.00s)
    --- FAIL: TestAdd/#00 (0.00s)
        f_test.go:35: Add(0,1) = 1, want 2
FAIL
exit status 1
FAIL    awesomeProject/testt    0.669s

帮助函数Helper()

改造上述测试函数,设定写法如下:

Go 复制代码
func TestAddWithHelper(t *testing.T) {
    type model struct {
        a, b int
        want int
    }

    execRun := func(t *testing.T, tt model) {
        // t.Helper()
        if got := Add(tt.a, tt.b); got != tt.want {
            t.Errorf("Add(%d,%d) = %d, want %d", tt.a, tt.b, got, tt.want)  // 52行
        }
    }

    execRun(t, model{a: 0, b: 1, want: 0})  // 56行 设定错误,模拟测试不通过
    execRun(t, model{a: 1, b: 2, want: 3})
}

多个自定义execRun在执行时都有出问题的可能,对于上述代码,当不加t.Helper()时提示如下:

Go 复制代码
--- FAIL: TestAddWithHelper (0.00s)
    f_test.go:52: Add(0,1) = 1, want 0
FAIL
FAIL    awesomeProject/testt    0.707s
FAIL

可以看到是t.Errorf这一行,不是特别直观,下面加上t.Helper(),结果如下:

Go 复制代码
--- FAIL: TestAddWithHelper (0.00s)
    f_test.go:56: Add(0,1) = 1, want 0
FAIL
FAIL    awesomeProject/testt    0.743s
FAIL

可以看到直接提示是56行的问题。

测试覆盖率

Go 复制代码
go test awesomeProject/testt -run TestAdd0 -cover

其中-cover测试表示本次测试启用覆盖率检测。

覆盖率的含义是,代码被测试套件覆盖的百分比,即测试中至少被运行一次的代码占总代码的比例。

将覆盖率结果生成报告:

Go 复制代码
go test awesomeProject/testt -run TestAdd0 -cover -coverprofile=a

如上,-coverprofile=a 参数会将覆盖率信息输出到文件a中,接着使用go tool调用本地浏览器来生成一个html格式的报告:

Go 复制代码
go tool cover -html=a

效果如下

加函数测试了,减函数未测试。

相关推荐
dreams_dream1 小时前
Django序列化器
后端·python·django
懷淰メ1 小时前
python3GUI--短视频社交软件 By:Django+PyQt5(前后端分离项目)
后端·python·django·音视频·pyqt·抖音·前后端
有意义1 小时前
从零搭建:json-server+Bootstrap+OpenAI 全栈 AI 小项目
前端·后端·llm
安冬的码畜日常2 小时前
【JUnit实战3_30】第十八章:REST API 接口测试(下)—— REST API 接口的 MockMvc + JUnit 5 测试实战
测试工具·junit·单元测试·restful·rest api·junit5
汤姆yu2 小时前
基于springboot的民间救援队救助系统
java·spring boot·后端·救援队
IT_陈寒2 小时前
React性能优化实战:这5个Hooks技巧让我的应用快了40%
前端·人工智能·后端
韩立学长3 小时前
基于Springboot的智慧管网灌溉系统i1agupa7(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
一 乐3 小时前
高校教务|教务管理|基于springboot+vue的高校教务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·教务管理
August_._3 小时前
【MySQL】触发器、日志、锁机制 深度解析
java·大数据·数据库·人工智能·后端·mysql·青少年编程
BingoGo4 小时前
15 个 Eloquent 高级技巧,瞬间提升你的 Laravel 应用性能
后端·php