单元测试函数类型

Test(功能测试)

函数规则:

  • 函数名: TestXxxx , 以Test为前缀。Xxxx以大写字母开头
  • 参数类型: *testing.T
func TestXxxx(t *testing.T){...}

编写一个简单的例子,假设有下面一个待测函数:


func add(a, b int) int {
return a + b
}

测试代码如下:

import "testing"

func TestAdd(t *testing.T) {
cases := []struct {
first int
second int
excepted int
}{
{1, 2, 3},
{1, 2, 4},
} for _, c := range cases {
result := add(c.first, c.second)
if result != c.excepted {
t.Fatalf("add function failed, first: %d, second:%d, execpted:%d, result:%d", c.first, c.second, c.excepted, result)
}
}
}

执行 go go test -v 结果如下:

=== RUN   TestAdd
--- FAIL: TestAdd (0.00s)
example_test.go:30: add function failed, first: 1, second:2, execpted:4, result:3
FAIL
exit status 1
FAIL gotest/gotest 0.006s

第二个测试用例出错,未能通过单元测试,需要检查测试数据或者被测试函数是否符合我们的预期。

从上述过程可以看出, TestXxxx 可以理解为功能性测试,其目的在于测试函数的功能性是否正确, 应当编写尽可能多的测试用例来验证被测函数的正确性。

Benchmark(基准测试)

函数规则:

  • 函数名: BenchmarkXxxx, 以Benchmark为前缀。Xxxx以大写字母开头
  • 参数类型: *testing.B
func BenchmarkXxx(b *testing.B){...}

性能测试函数如下:

func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
add(1, 2)
}
}

执行 go test -bench=. -run=^$,结果如下:

goos: darwin
goarch: amd64
pkg: gotest/gotest
BenchmarkAdd-8 2000000000 0.32 ns/op
PASS
ok gotest/gotest 0.667s

测试结果说明:

  • -8 表示 8个逻辑cpu个数(下文会解释)
  • 2000000000 表示执行了 2000000000 次
  • 0.32 ns/op 每次操作耗时
  • 0.667s 是总时长

性能测试函数计时器:

当性能测试函数中有一些额外的初始化操作时,可以通过启停计时器来屏蔽这些操作对最终性能测试的影响。简单例子如下:

func BenchmarkAdd(b *testing.B) {
time.Sleep(10 * time.Second)
for i := 0; i < b.N; i++ {
add(1, 2)
}
}

执行命令go test -bench=.,结果如下:

goos: darwin
goarch: amd64
pkg: gotest/gotest
BenchmarkAdd-8 1 10004479538 ns/op
PASS
ok gotest/gotest 10.011s

单个测试函数耗时为 10004479538 ns,同时我们也可以看到,这个函数执行一次就已经达到了最大上限时间。

加上时间计数器:

func BenchmarkAdd(b *testing.B) {
b.StopTimer()
time.Sleep(10 * time.Second)
b.StartTimer()
for i := 0; i < b.N; i++ {
add(1, 2)
}
}

测试结果如下:

goos: darwin
goarch: amd64
pkg: gotest/gotest
BenchmarkAdd-8 2000000000 0.34 ns/op
PASS
ok gotest/gotest 60.751s

单次执行耗时为: 0.34 ns 了。

Tips:

对于 b.N 参数而言, test 命令先会尝试设置为1,之后执行函数。如果测试函数没有达到执行上限的话, test 函数会增大,之后再次执行测试函数,如此往复,直到执行时间大于或者等于上限时间为止。 上限时间可以使用 -benchtime设定

Example(示例测试)

函数规则:

  • 函数名: ExampleXxx
  • 输出内容至标准输出,参数列表没有限制

示例测试函数如下:

func Println(content string) {
fmt.Println("The output of\nthis example.")
}
func ExamplePrintln() {
Println("The output of\nthis example.")
// Output: The output of
// this example.
}

go test 命令会检测实际输出与注释中的期望输出是否一致, 一致则测试通过,不一致则测试失败。

go test 常用参数

  • -cpu: 设置测试最大 cpu 逻辑数(也就是 GPM 中 P, 最大并行执行的 gorouting 数量, 默认等于 cpu 核数)
  • -count: 设置执行测试函数的次数, 默认为 1
  • -run: 执行功能测试函数, 支持正则匹配, 可以选择测试函数或者测试文件来仅测试单个函数或者单个文件
  • -bench: 执行基准测试函数, 支持正在匹配
  • -benchtime: 基准测试最大探索时间上限
  • -parallel: 设置同一个被测试代码包中的功能测试函数的最大并发执行数
  • -v: 是展示测试过程信息

更多的参数可以参考下文的官方文档

参考

golang 官方文档

极客时间

golang 单元测试(一)的更多相关文章

  1. ARTS-S golang单元测试

    golang单元测试 在$GOPATH的src目录下建目录demo_unittest 在目录demo_unittest下建文件calc.go,内容如下: package demo_unittest f ...

  2. Golang单元测试框架整理

    目录 一.单元测试是什么 二.单元测试的意义 三.Golang单元测试框架 3.1 Golang内置testing包 3.1.1 简单的测试 3.1.2 Benchmark 基准测试 3.1.3 运行 ...

  3. golang单元测试

    使用testing进行单元测试 golang的测试库testing 测试文件与被测试文件在同一个包中 测试文件名为被测试文件名(去后缀)_test.go 测试用例函数以Test开头,TestFunc1 ...

  4. golang 单元测试

    单元测试是质量保证十分重要的一环,好的单元测试不仅能及时地发现问题,更能够方便地调试,提高生产效率.所以很多人认为写单元测试是需要额外的时间,会降低生产效率,是对单元测试最大的偏见和误解. go 语言 ...

  5. golang 单元测试&&性能测试

    一:单元测试 1.为什么要做单元测试和性能测试 减少bug 快速定位bug 减少调试时间 提高代码质量 2.golang的单元测试 单元测试代码的go文件必须以_test.go结尾 单元测试的函数名必 ...

  6. golang单元测试简述

      Golang中内置了对单元测试的支持,不需要像Java一样引入第三方Jar才能进行测试,下面将分别介绍Golang所支持的几种测试: 一.测试类型   Golang中单元测试有功能测试.基准测试. ...

  7. golang单元测试一(简单函数测试)

    0.1.索引 https://blog.waterflow.link/articles/1663688140724 1.简介 单元测试是测试代码.组件和模块的单元函数.单元测试的目的是清除代码中的错误 ...

  8. 【GoLang】GoLang 单元测试、性能测试使用方法

    单元测试代码: ackage test import ( // "fmt" "testing" ) func Test_FlowControl(t *testi ...

  9. Golang 单元测试和性能测试

    开发程序其中很重要的一点是测试,我们如何保证代码的质量,如何保证每个函数是可运行,运行结果是正确的,又如何保证写出来的代码性能是好的,我们知道单元测试的重点在于发现程序设计或实现的逻辑错误,使问题及早 ...

随机推荐

  1. intellij idea tomcat 启动不生成war包

    intellij idea tomcat 启动不生成war包 想把项目打包成war包做测试,但是按照之前的方法居然没有成功导出war包,犯了很低级的错误,特此记录. (1)首先在Project Str ...

  2. C图形化第一步

    之前的贪吃蛇都是在cmd下实现,每次都要调用cls刷新屏幕,简直是闪瞎了我的狗眼. 度娘得知有一种方法可以避免闪烁,即:双缓冲.原理是先在内存中作图,然后将做好的图复制到前台,同时禁止背景刷新. 主要 ...

  3. NPAPI绘图和事件处理

    https://developer.mozilla.org/en-US/docs/Plugins/Guide/Drawing_and_Event_Handling 本章介绍如何确定插件实例是窗口化还是 ...

  4. 人脸替换(FaceSwap)的一些思考

    本文链接:https://blog.csdn.net/cy1070779077/article/details/85224347人脸替换(FaceSwap)的一些思考 最一开始,我使用了openCV( ...

  5. IM 简介

    LayIM - 打造属于你自己的网页聊天系统http://layim.layui.com/ 瓜子IM智能客服系统的数据架构设计(整理自现场演讲) - 知乎https://zhuanlan.zhihu. ...

  6. 移动端IM系统的协议选型:UDP还是TCP?(转)

    源: 移动端IM系统的协议选型:UDP还是TCP?

  7. 从0开始学爬虫4之requests基础知识

    从0开始学爬虫4之requests基础知识 安装requestspip install requests get请求:可以用浏览器直接访问请求可以携带参数,但是又长度限制请求参数直接放在URL后面 P ...

  8. 【转】用python读写excel的强大工具:openpyxl

    最近看到好几次群里有人问xlwt.wlrd的问题,怎么说呢,如果是office2007刚出来,大家用xlsx文件用不习惯,还可以理解,这都10年过去了喂,就算没有进化到office2016,还在用of ...

  9. php报错syntax error, unexpected T_GOTO, expecting T_STRING,报错文件与行数指向以下代码,是什么原因?

    本机php版本是5.3.8,Apache/2.2.21public function goto($url, $msg=NULL) {if ($msg) {$this->jsAlert($msg) ...

  10. 一行命令学会全基因组关联分析(GWAS)的meta分析

    为什么需要做meta分析 群体分层是GWAS研究中一个比较常见的假阳性来源. 也就是说,如果数据存在群体分层,却不加以控制,那么很容易得到一堆假阳性位点. 当群体出现分层时,常规手段就是将分层的群体独 ...