单元测试
- 什么是单元测试?
- 指在计算机编程中
针对一块特定的模块、组件、方法
进行测试以验证其是否满足业务、质量需求的测试方法
- 怎么写单元测试?
- 单元测试关键组成部分
- 预备案例
- 预期结果
- 组件调用
- 衡量预算
- Golang 针对单元测试,有2种测试方式
- 黑盒测试
- 测试案例和源码在同一个目录下,但是不在同一个包中
- 测试案例仅针对目标包里暴露出来的共有方法进行测试
- 白盒测试
- 测试案例和源码在同一个目录下,同一个包中
- 测试案例可以看到同一个包中的
私有变量、方法
,可以针对每一项进行测试
- 黑盒测试
- Golang的单元测试编写规则
- 文件名必须以
_test.go
结尾 - 必须符合命名规则
func TestXxxx(t *testing.T){}
,首单词Test
- testing 是golang的内置包,用来做单元测试的
- 对预期失败的case,需要调用
- t.Fail()、t.FailNow()、t.Error(...)、t.Errorf()、t.Fatal(...)、t.Fatalf(...)等来声明失败
- 文件名必须以
package calctest
import (
"testing"
)
func TestMain(t *testing.T) {
height, weight := 1.0, 1.0
output := 1.0
t.Log("开始计算,输入height: %f, weight: %f", height, weight)
actualOutput, err := CalcBMI(height, weight)
if err != nil {
t.Errorf("计算出错了%v", err)
}
if actualOutput != output {
t.Errorf("计算出错了actualOutput: %f, output: %f", actualOutput, output)
// t.Fail()//测试失败
}
}
- 怎么运行单元测试?
- 运行命令:
go test <package path>
- 后面指的是
文件夹路径
- 后面指的是
- 怎么单步调试单元测试?
- 配合开发工具使用
单元测试
- 用来验证函数逻辑是否正确
- 文件名称改为
xxx_test.go
- 文件内部必须有
Test为前缀的
函数
例子1 bytedance/sonic 和 json的单元测试
- 通过
go test xxx_test.go
来执行单元测试go test xxx_test.go -v
-> -v让Println可正常执行- 默认 fmt.Println是不会输出的
- 如果只想运行某个/某类 测试函数写法如下
go test xxx_test.go -v -run=TestJson
-> 只运行TestJson函数go test xxx_test.go -v -run=Json
-> 回去找匹配的函数执行
package main
import (
"encoding/json"
"bytedance/sonic"
"fmt"
"testing"
)
type Student struct {
Name string
Age int
Gender bool
}
type Class struct {
Id string
Students []Student
}
var (
s = Student{"张三", 18, true}
c = Class{
Id: "001",
Students: []Student{s, s}
}
)
func TestJson(t *testing.T) {
bytes, err := json.Marshal(c)
if err != nil {
t.Fail()//就会终止下面的执行
}
var c2 Class
err = json.Unmarshal(bytes, &c2)
if err != nil {
t.Fail()//就会终止下面的执行
}
if !(c.Id == c2.Id && len(c.Students) == len(c2.Students)) {
t.Fail()
}
fmt.Println("json测试通过")
}
func JsonSonic(t *testing.T) {
bytes, err := sonic.Marshal(c)
if err != nil {
t.Fail()//就会终止下面的执行
}
var c2 Class
err = sonic.Unmarshal(bytes, &c2)
if err != nil {
t.Fail()//就会终止下面的执行
}
if !(c.Id == c2.Id && len(c.Students) == len(c2.Students)) {
t.Fail()
}
fmt.Println("sonic测试通过")
}
基准测试
- 用来做性能测试的,会返回执行
- 文件名称改为
xxx_test.go
- 文件内部必须有
Benchmark为前缀的
函数
例子2 bytedance/sonic 和 json的性能测试
go test -bench=Json json_test.go
- 加 -benchmem可以获取内存情况
package main
import (
"encoding/json"
"bytedance/sonic"
"fmt"
"testing"
)
type Student struct {
Name string
Age int
Gender bool
}
type Class struct {
Id string
Students []Student
}
var (
s = Student{"张三", 18, true}
c = Class{
Id: "001",
Students: []Student{s, s}
}
)
func BenchmarkJson(b *testing.B) {
// b.N 不是一个常量 会根据实际的运行耗时动态取值,N是个很大的数
for i := 0; i < b.N; i++ {
// 不关心逻辑是否正确
bytes, _ := json.Marshal(c)
var c2 Class
json.Unmarshal(bytes, &c2)
fmt.Println("json测试通过")
}
}
func BenchmarkSonic(b *testing.B) {
for i := 0; i < b.N; i++ {
// 不关心逻辑是否正确
bytes, _ := sonic.Marshal(c)
var c2 Class
sonic.Unmarshal(bytes, &c2)
fmt.Println("json测试通过")
}
}