Go 测试(模糊、基准、单元测试)
[toc]
单元测试
Go语言中自带轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试
单元测试能及时发现程序设计或者实现的逻辑错误,而性能测试能使程序在高并发的状态下还能保持稳定。
什么是可靠的性能基准测试环境
影响测试环境的软硬件因素:
- 硬件:CPU型号、温度、IO等
- 软件:操作系统版本、当前系统调度的负载等等
指导思想:
单次测试结构毫无意义,统计意义下 可对比的结果 是关键
- 分析测试的场景、多次测试、决定统计检验的类型
可对比的结果是在可控的环境下得到的:
- 笔记本电脑 CPU 的执行效率受电源管理等因素影响,连续测试同一段代码可能先得到短暂的性能提升,而后由于温度上升导致性能下降。
- 虚拟机或者云服务器可能因为资源分配因素导致测量结果不稳定。
所以基准测试的两个基本目标
- 可重复性:在其他外在条件不变的条件下,性能度量结果是稳定的、可重复性的
- 可比较性:总是存在一个可以比较的基本线
测试用例的编写规则
测试规则:
- 测试用例文件必须以
_test
结尾,例如:util_test.go
- 功能测试用例方法必须
Test
开头 - 模糊测试用例方法必须
Fuzz
开头 - 基准测试用例方法必须
Benchmark
开头 - 文件夹
_test
结尾的测试包,会被编译成分离包 go help test
、go help testflag
查看帮助
go test 模式
提示
我们可以使用在线环境进行测试,正好有一个在线的测试 k3s-runtime 我们使用它来构建。
1. 本地模式: go test
或者 go test -v
2. 列表模式:编译并运行命令行上列出的每一个包,go test util
、go test ./
等
go-test 命令
注意:
go test
会编译所有 *_test.go
文件的包,这些文件可以包含 功能测试、banchmark测试、模糊测试。 所有以 _
和 .
开头的文件都会被忽略,包括 _test.go
在 go test
前会运行 go vet
测试文件签名问题,如果在 go vert
过程中发现问题,将停止运行 go test
。
go test
的两种模式:
go test
编译运行当前文件测试文件。侧重模式下不caching
go test .
,go test math
,go test ./...
go test
运行时,工作目录为被测试包所在的位置。
其他的一些参数
-benchtime t
:指定测试时间,比如 1s 指定运行 1s-count n
: 指定运行多少次用例。如果-cpu
指定了 cpu 数量,运行次数将会是[n * cpu]
-cover
:输出代码测试覆盖率-json
:以json方式输出测试报告-failfast
:一个测试用例失败后不去测试其他的测试用例-run regexp
:指定运行测试的规则-cpu 1,2,4
:指定 cpu 数量,会基于一个 cpu 跑一起,基于 2 个 cpu 跑一次,基于 4 个跑一次。对于benchmarks和模糊测试有意义。
测试用例
💡简单的一个案例如下:
package util
/* 测试用例,必须以util_test命名 */
import (
"fmt"
"testing"
)
var commTestData []commStruct
// 定义全局变量,用于测试
type commStruct struct {
// 代码块
Group string
SizeStr string //输入
Expected int64 //期望值
Expected string //期望值
}
// 功能测试:主要验证功能是否正常
func TestParseSize(t *testing.T) {
testData := commTestData
for _, v := range testData {
if v.Group == "ParseSize" {
actual := ParseSize(v.SizeStr)
if actual != v.Expected {
t.Errorf("ParseSize(%s) = %d, expected %d", v.SizeStr, actual, v.Expected)
}
}
}
}
// 模糊测试
func TestFuzzy(t *testing.T) {
fmt.Println("util_test.go")
}
// 精确测试
func TestExact(t *testing.T) {
fmt.Println("util_test.go")
}
// 性能测试
func Benchmark(b *testing.B) {
fmt.Println("util_test.go")
}
// 基准测试
func Benchmark(b *testing.B) {
fmt.Println("util_test.go")
}
// TestMain函数,用于测试前的初始化
func TestMain(m *testing.M) {
initCommonData()
}
func initCommonData() {
commTestData = []commStruct{ //测试数据
{"ParseSize", "1", 1, "1"},
{"ParseSize", "1k", 1024, "1k"},
{"ParseSize", "1m", 1024 * 1024, "1m"},
{"ParseSize", "1g", 1024 * 1024 * 1024, "1g"},
{"ParseSize", "1t", 1024 * 1024 * 1024 * 1024, "1t"},
{"ParseSize", "1p", 1024 * 1024 * 1024 * 1024 * 1024, "1p"},
{"ParseSize", "1e", 1024 * 1024 * 1024 * 1024 * 1024 * 1024, "1e"},
{"ParseSize", "1z", 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, "1z"},
}
m.Run()
}
END 链接
✴️版权声明 © :本书所有内容遵循CC-BY-SA 3.0协议(署名-相同方式共享)©