测试对于互联网应用软件开发来说非常重要,它对软件可靠性保证具有重要意义,通过测试能够尽可能发现并改正软件中的错误,提高软件质量。

这里我们主要讲解Go语言如何实现单元测试和性能测试。

go语言中自带有一个轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试,testing框架和其他语言中的测试框架类似,你可以基于这个框架写针对相应函数的测试用例,也可以基于该框架写相应的压力测试用例,那么接下来让我们一一来看一下怎么写。

单元测试

创建目录test,在目录下创建add.go、add_test.go两个文件,add_test.go为单元测试文件。

add_test.go

package testimport "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")}
}
func TestAdd1(t *testing.T) {t.Error("the result is error")
}

add.go

package testfunc Add(a, b int) int {return a + b
}

然后在项目目录下运行go test -v就可以看到测试结果了

=== RUN   TestAdd
--- PASS: TestAdd (0.00s)add_test.go:8: the result is ok
=== RUN   TestAdd1
--- FAIL: TestAdd1 (0.00s)add_test.go:14: the result is error
FAIL
exit status 1
FAIL    _/D_/gopath/src/ados/test       0.419s

如果看到PASS字样证明测试通过,FAIL字样表示测试失败。

使用testing库的测试框架需要遵循以下几个规则如下:

  • 文件名必须是_test.go结尾的,这样在执行go test的时候才会执行到相应的代码
  • 你必须import testing这个包
  • 所有的测试用例函数必须是Test开头
  • 测试用例会按照源代码中写的顺序依次执行
  • 测试函数TestXxx()的参数是testing.T,我们可以使用该类型来记录错误或者是测试状态
  • 测试格式:func TestXxx (t *testing.T),Xxx部分可以为任意的字母数字的组合,但是首字母不能是小写字母[a-z],例如Testintdiv是错误的函数名。
  • 函数中通过调用testing.TError, Errorf, FailNow, Fatal, FatalIf方法,说明测试不通过,调用Log方法用来记录测试的信息。

性能测试或压力测试

压力测试用来检测函数(方法)的性能,和编写单元功能测试的方法类似,此处不再赘述,但需要注意以下几点:

  • 压力测试用例必须遵循如下格式,其中XXX可以是任意字母数字的组合,但是首字母不能是小写字母

    func BenchmarkXXX(b *testing.B) { ... }
    
  • go test不会默认执行压力测试的函数,如果要执行压力测试需要带上参数-test.bench,语法:-test.bench="test_name_regex",例如go test -test.bench=".*"表示测试全部的压力测试函数

  • 在压力测试用例中,请记得在循环体内使用testing.B.N,以使测试可以正常的运行

  • 文件名也必须以_test.go结尾

在test目录下创建 reflect_test.go

package testimport ("reflect""testing"
)type Student struct {Name  stringAge   intClass stringScore int
}func BenchmarkReflect_New(b *testing.B) {var s *Studentsv := reflect.TypeOf(Student{})b.ResetTimer()for i := 0; i < b.N; i++ {sn := reflect.New(sv)s, _ = sn.Interface().(*Student)}_ = s
}
func BenchmarkDirect_New(b *testing.B) {var s *Studentb.ResetTimer()for i := 0; i < b.N; i++ {s = new(Student)}_ = s
}
func BenchmarkReflect_Set(b *testing.B) {var s *Studentsv := reflect.TypeOf(Student{})b.ResetTimer()for i := 0; i < b.N; i++ {sn := reflect.New(sv)s = sn.Interface().(*Student)s.Name = "Jerry"s.Age = 18s.Class = "20005"s.Score = 100}
}
func BenchmarkReflect_SetFieldByName(b *testing.B) {sv := reflect.TypeOf(Student{})b.ResetTimer()for i := 0; i < b.N; i++ {sn := reflect.New(sv).Elem()sn.FieldByName("Name").SetString("Jerry")sn.FieldByName("Age").SetInt(18)sn.FieldByName("Class").SetString("20005")sn.FieldByName("Score").SetInt(100)}
}
func BenchmarkReflect_SetFieldByIndex(b *testing.B) {sv := reflect.TypeOf(Student{})b.ResetTimer()for i := 0; i < b.N; i++ {sn := reflect.New(sv).Elem()sn.Field(0).SetString("Jerry")sn.Field(1).SetInt(18)sn.Field(2).SetString("20005")sn.Field(3).SetInt(100)}
}
func BenchmarkDirect_Set(b *testing.B) {var s *Studentb.ResetTimer()for i := 0; i < b.N; i++ {s = new(Student)s.Name = "Jerry"s.Age = 18s.Class = "20005"s.Score = 100}
}

在test目录下,执行:

go test reflect_test.go -test.bench=".*"

结果如下

goos: windows
goarch: amd64
BenchmarkReflect_New-4                  20000000                84.9 ns/op
BenchmarkDirect_New-4                   30000000                50.6 ns/op
BenchmarkReflect_Set-4                  20000000                89.9 ns/op
BenchmarkReflect_SetFieldByName-4        3000000               552 ns/op
BenchmarkReflect_SetFieldByIndex-4      10000000               132 ns/op
BenchmarkDirect_Set-4                   30000000                53.0 ns/op
PASS
ok      command-line-arguments  10.982s

上面的结果显示我们没有执行任何TestXXX的单元测试函数,显示的结果只执行了压力测试函数,以第三行为例

BenchmarkReflect_New 函数执行了20000000次,每次的执行平均时间是84.9纳秒。最后一行 command-line-arguments 10.982s,代表总的执行时间为 10.982s。

如果只想对某个函数测试,以BenchmarkReflect_New 为例,执行命令

go test reflect_test.go -test.bench=“BenchmarkReflect_New”

结果为:

goos: windows
goarch: amd64
BenchmarkReflect_New-4          20000000                84.9 ns/op
PASS
ok      command-line-arguments  2.490s

如果测试整个目录下的所有测试执行:

go test -test.bench=".*"

如果想显示内存分配的次数和大小添加 -benchmem

go test reflect_test.go -benchmem -test.bench=".*"

goos: windows
goarch: amd64
BenchmarkReflect_New-4                  20000000   88.3 ns/op  48 B/op     1 allocs/op
BenchmarkDirect_New-4                   30000000   53.8 ns/op  48 B/op     1 allocs/op
BenchmarkReflect_Set-4                  20000000   90.9 ns/op  48 B/op     1 allocs/op
BenchmarkReflect_SetFieldByName-4        3000000   564 ns/op   80 B/op     5 allocs/op
BenchmarkReflect_SetFieldByIndex-4      10000000   135 ns/op   48 B/op     1 allocs/op
BenchmarkDirect_Set-4                   30000000   52.4 ns/op  48 B/op     1 allocs/op
PASS
ok      command-line-arguments  12.955s

后两列代表分配的内存大小和次数(48 B/op 1 allocs/op)

推荐gotests

它是编写Go测试的一个Golang命令行工具,可以根据目标源文件的函数和方法签名生成表驱动的测试。将自动导入测试文件中的任何新依赖项。

参考:

https://studygolang.com/static/pkgdoc/pkg/testing.htm

https://www.cnblogs.com/yjf512/archive/2013/01/22/2870927.html

  • 目录

Go 单元测试和性能测试相关推荐

  1. golang 单元测试和性能测试

    单元测试 单元测试(Unit Tests, UT) 是一个优秀项目不可或缺的一部分,特别是在一些频繁变动和多人合作开发的项目中尤为重要.你或多或少都会有因为自己的提交,导致应用挂掉或服务宕机的经历.比 ...

  2. 软件测试nodejs面试题,nodejs单元测试和性能测试

    好算法理应正确.可读.健壮和效率高与低存储量:为保证正确性,多组输入数据测试这是必须条件:效率高和低存储这涉及了接口代码的性能测试.测试驱动开发TDD以实现有效和高效的算法代码. 一.安装配置 确保已 ...

  3. golang 单元测试

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

  4. WebApi管理和性能测试工具WebApiBenchmarks

    说到WebApi管理和测试工具其实已经非常多的了,Postman.Swagger等在管理和维护上都非常出色:在性能测试方面也有不少的工具如:wrk,bombardier,http_load和ab等等. ...

  5. Golang——单元测试testing

    Go语言中带有一个轻量级的测试框架testing和go test命令来实现单元测试及性能测试.单元测试可以解决 确保每个函数都是可运行且结果正确 确保代码性能完好 单元测试可以及时发现程序设计或实现的 ...

  6. Golang笔记——单元测试

    单元测试 先看一个需求 在我们工作中,我们会遇到这样的情况,就是去确认一个函数,或者一个模块的结果是否正确, 如: 传统的方法 传统的方式来进行测试 在 main 函数中,调用 addUpper 函数 ...

  7. 性能测试、 障碍条件和回滚

    第17章 性能测试 1. 性能测试是指把负载和用户需求施加在系统上,以测量其相应时间和稳定性的过程,它是为了验证应用能够满足预期的性能目标:一般需要关注响应时间.吞吐量和资源利用率这三类指标: 2. ...

  8. 深入理解Go语言中的函数【单元测试】14

    文章目录 go test工具 测试函数 测试函数的格式 测试函数示例 测试组 子测试 测试覆盖率 基准测试 基准测试函数格式 基准测试示例 性能比较函数 重置时间 并行测试 Setup与TearDow ...

  9. Golang单元测试、Mock测试以及基准测试

    之前参加字节跳动青训营而整理的笔记 Golang拥有一套单元测试和性能测试系统,仅需要添加很少的代码就可以快速测试一段需求代码. 一.单元测试 单元测试主要包括:输入.测试单元.输出.期望以及与期望的 ...

最新文章

  1. sqlldr,将数据批量导入Oracle数据库
  2. JavaScript——易班优课YOOC课群在线测试答案隐藏解决方案
  3. 欢乐ssl暑假赛【2019.8.6】
  4. 给APK签名,修改签名
  5. [css] css中的border:none和border:0px有什么区别?
  6. html中的行内标签吗,HTML标签中行内元素和块级元素详解
  7. 线性表—顺序表-顺序表基本运算的实现
  8. mysql分页总页数算法解析_详解MySQL的limit用法和分页查询语句的性能分析
  9. Nginx(6)-配置基于域名的虚拟主机
  10. express基本原理
  11. Django中的views
  12. 最强大脑记忆曲线(5)——主程序设计
  13. 2017年的博客之路开始---下一个十年
  14. 8脚 tja1050t_TJA1050T设计的CAN总线通信硬件电路原理图解
  15. 信号与系统 chapter7 因果与非因果
  16. 达人评测 联想小新Pro16和小米笔记本Pro15选哪个好
  17. STL 源码分析: RB_tree 红黑树(三) 插入和查找
  18. 机器学习入门 - Google的机器学习速成课程
  19. jtable如何从表格中定位_ja中怎样将一个JTable表中的指定行添加到数据库
  20. ESP32 Ubuntu开发环境搭建

热门文章

  1. 第七周总结CoreIDRAW
  2. 腾讯理财通运营主体迁至腾讯旗下腾富公司
  3. SVN使用 IDEA集成SVN SVN简介 SVN使用详解 SVN学习之路
  4. [转载]致创业者:APP已死 服务永生
  5. 1106. 解析布尔表达式
  6. 微信小程序地图定位GPS转腾讯地图的坐标系
  7. mysql 储存过程放到哪_MySQL储存过程详解
  8. 逆向教程-游戏中的U3D付费模式分析
  9. [勇者闯LeetCode] 155. Min Stack
  10. 机器学习需要哪些基础知识?