# 6.2 单元测试:如何进行单元测试?
在计算机编程中,单元测试(英语:Unit Testing)又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。
程序单元是应用的最小可测试部件,一般来说都是对某一个函数方法进行测试,以尽可能的保证没有问题或者问题可被我们预知。为了达到这个目的,我们可以使用各种手段、逻辑,模拟不同的场景进行测试。
那么我们如何在写 Golang 代码时,进行单元测试呢?
由于实在是太简单了,我这里直接上例子吧
## 1. 单元测试
准备两个 Go 文件
**math.go**
```go
package math
func Add(x,y int) int {
return x+y
}
```
**math_test.go**
```go
package math
import "testing"
func TestAdd(t *testing.T) {
t.Log(Add(1, 2))
}
```
然后使用 `go test` 工具去执行
```shell
$ go test .
ok _/home/wangbm/golang/math 0.003s
```
从上面这个例子中,可以总结中几点 Go 语言测试框架要遵循的规则
1. 单元测试代码的 go文件必须以`_test.go`结尾,而前面最好是被测试的文件名(不过并不是强制的),比如要测试 math.go 测试文件名就为 math_test.go
2. 单元测试的函数名必须以`Test`开头,后面直接跟要测试的函数名,比如要测试 Add函数,单元测试的函数名就得是 TestAdd
3. 单元测试的函数必须接收一个指向`testing.T`类型的指针,并且不能返回任何值。
## 2. 表组测试
Add(1, 2) 是一次单元测试的场景,而 Add(2, 4) ,Add(3, 6) 又是另外两种单元测试的场景。
对于多种输入场景的测试,我们可以同时放在 TestAdd 里进行测试,这种测试方法就是表组测试。
修改 **math_test.go** 如下
```go
package math
import "testing"
func TestAdd(t *testing.T) {
sum:=Add(1,2)
if sum == 3 {
t.Log("the result is ok")
} else {
t.Fatal("the result is wrong")
}
sum=Add(2,4)
if sum == 6 {
t.Log("the result is ok")
} else {
t.Fatal("the result is wrong")
}
}
```
执行 `go test `
```shell
$ go test . -v
=== RUN TestAdd
TestAdd: math_test.go:8: the result is ok
TestAdd: math_test.go:15: the result is ok
--- PASS: TestAdd (0.00s)
PASS
ok _/home/wangbm/golang/math 0.003s
```
稍微如果输入的场景实在太多(比如下面用的五组输入),用上面的方法,可能需要写很多重复的代码,这时候可以利用 **表格测试法**
```go
package math
import "testing"
type TestTable struct {
xarg int
yarg int
}
func TestAdd(t *testing.T){
tables := []TestTable{
{1,2},
{2,4},
{4,8},
{5,10},
{6,12},
}
for _, table := range tables{
result := Add(table.xarg, table.yarg)
if result == (table.xarg + table.yarg){
t.Log("the result is ok")
} else {
t.Fatal("the result is wrong")
}
}
}
```
执行 `go test`
```shell
$ go test . -v
=== RUN TestAdd
TestAdd: math_test.go:22: the result is ok
TestAdd: math_test.go:22: the result is ok
TestAdd: math_test.go:22: the result is ok
TestAdd: math_test.go:22: the result is ok
TestAdd: math_test.go:22: the result is ok
--- PASS: TestAdd (0.00s)
PASS
ok _/home/wangbm/golang/math 0.002s
```
- 第一章:基础知识
- 1.1 一文搞定开发环境的搭建
- 1.2 五种变量创建的方法
- 1.3 数据类型:整型与浮点型
- 1.4 数据类型:byte、rune与字符串
- 1.5 数据类型:数组与切片
- 1.6 数据类型:字典与布尔类型
- 1.7 数据类型:指针
- 1.8 流程控制:if-else
- 1.9 流程控制:switch-case
- 1.10 流程控制:for 循环
- 1.11 流程控制:goto 无条件跳转
- 1.12 流程控制:defer 延迟语句
- 1.13 流程控制:理解 select 用法
- 1.14 异常机制:panic 和 recover
- 1.15 语法规则:理解语句块与作用域
- 第二章:面向对象
- 2.1 面向对象:结构体与继承
- 2.2 面向对象:接口与多态
- 2.3 面向对象:结构体里的 Tag 用法
- 2.4 学习接口:详解类型断言
- 2.5 学习接口:Go 语言中的空接口
- 2.6 学习接口:接口的三个"潜规则"
- 2.7 学习反射:反射三定律
- 2.8 学习反射:全面学习反射的函数
- 2.9 详细图解:静态类型与动态类型
- 2.10 关键字:make 和 new 的区别?
- 第三章:项目管理
- 3.1 依赖管理:包导入很重要的 8 个知识点
- 3.2 依赖管理:超详细解读 Go Modules 应用
- 3.3 开源发布:如何开源自己写的包给别人用?
- 3.4 代码规范:Go语言中编码规范
- 第四章:并发编程
- 4.1 学习 Go 函数:理解 Go 里的函数
- 4.2 学习 Go 协程:goroutine
- 4.3 学习 Go 协程:详解信道/通道
- 4.4 学习 Go 协程:WaitGroup
- 4.5 学习 Go 协程:互斥锁和读写锁
- 4.7 学习 Go 协程: 信道死锁经典错误案例
- 4.7 学习 Go 协程:如何实现一个协程池?
- 4.8 理解 Go 语言中的 Context
- 4.9 学习一些常见的并发模型
- 第五章:学标准库
- 5.1 fmt.Printf 方法详解
- 5.2 os/exec 执行命令的五种姿势
- 第六章:开发技能
- 6.1 Go 命令:go test 工具详解
- 6.2 单元测试:如何进行单元测试?
- 6.3 调试技巧:使用 GDB 调试 Go 程序
- 6.4 Go 命令: Go 命令指南
- 第七章:暂未分类
- 7.1 20 个学习 Go 语言的精品网站
