Golang 单元测试与性能测试

Go 自带了测试框架和工具,在 testing 包中,以便完成单元测试(T 类型)和性能测试(B 类型)。一般测试代码放在*_test.go 文件中,与被测代码放于同一个包中。

单元测试

测试函数名称格式是:Test[^a-z],即以 Test 开头,跟上非小写字母开头的字符串。每个测试函数都接受一个testing.T 类型参数,用于输出信息或中断测试。

测试方法有:

  • Fail: 标记失败,但继续执行当前测试函数
  • FailNow: 失败,立即终止当前测试函数执行
  • Log: 输出错误信息
  • Error: Fail + Log
  • Fatal: FailNow + Log
  • Skip: 跳过当前函数,通常用于未完成的测试用例

测试代码:

// filename: add_test.go

package test
import (
    "testing"
)

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

func TestAdd1(t *testing.T) {
    if Add(2, 3) != 5 {
         t.Error("result is wrong!")
    } else {
         t.Log("result is right")
    }
}

func TestAdd2(t *testing.T) {
    if Add(2, 3) != 6 {
         t.Fatal("result is wrong!")
    } else {
         t.Log("result is right")
    }
}

运行以下命令,自动搜集所有的测试文件(*_test.go),提取全部测试函数。

$ go test
输出:
--- FAIL: TestAdd2 (0.00s)
    add_test.go:20: result is wrong!
FAIL
exit status 1
FAIL    _/Users/golang_learning/testTB  0.006s

输出结果包括:出错的测试函数名称,执行时长和错误信息

go test 还有以下参数:

  • -v:显示所有测试函数运行细节
$ go test -v
输出:
=== RUN   TestAdd1
--- PASS: TestAdd1 (0.00s)
    add_test.go:14: result is right
=== RUN   TestAdd2
--- FAIL: TestAdd2 (0.00s)
    add_test.go:20: result is wrong!
FAIL
exit status 1
FAIL    _/Users/golang_learning/testTB  0.007s
  • -run regex:指定要执行的测试函数
$ go test -run TestAdd2
输出:
--- FAIL: TestAdd2 (0.00s)
    add_test.go:20: result is wrong!
FAIL
exit status 1
FAIL    _/Users/golang_learning/testTB  0.006s

性能测试

性能测试函数以 Benchmark 开头,参数类型是 testing.B,可与 Test 函数放在同个文件中。默认情况下,go test 不执行 Benchmark 测试,必须用-bench <pattern>指定性能测试函数。

测试代码:

// filename: add_test.go
package test
import (
    "testing"
)

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

func Benchmark(b *testing.B) {
    for i := 0; i < b.N; i++ { // b.N,测试循环次数
        Add(4, 5)
    }
}

执行命令测试:

$ go test -bench=.
输出:
goos: darwin
goarch: amd64
Benchmark-4     2000000000           0.35 ns/op
PASS
ok      _/Users/golang_learning/testTB  0.753s

B 类型也有以下参数:

  • benchmem:输出内存分配统计
  • benchtime:指定测试时间
  • cpu:指定 GOMAXPROCS
  • timeout:超时限制
$ go test -v -bench=. -cpu=8 -benchtime="3s" -timeout="5s" -benchmem
输出:
goos: darwin
goarch: amd64
Benchmark-8     5000000000           0.34 ns/op        0 B/op          0 allocs/op
PASS
ok      _/Users/golang_learning/testTB  1.766s
  • Benchmark-8:-cpu 参数指定,-8 表示 8 个 CPU 线程执行
  • 5000000000:表示总共执行了 5000000000 次
  • 0.34 ns/op:表示每次执行耗时 0.34 纳秒
  • 0 B/op:表示每次执行分配的内存(字节)
  • 0 allocs/op:表示每次执行分配了多少次对象

pprof

go tools 继承了 pprof,以便进行性能测试并找出瓶颈。

测试数据文件生成有两种方法:命令行和代码

命令行生成测试数据文件

$ go test -bench=. -cpuprofile cpu.out
输出:
goos: darwin
goarch: amd64
Benchmark-4     2000000000           0.35 ns/op
PASS
ok      _/Users/golang_learning/testTB  0.911s
$ ls
输出:(上一条命令生成cpu.out和testTB.test)
add_test.go     cpu.out     testTB.test

用命令行分析

$ go tool pprof -text mem.out
输出:
Main binary filename not available.
Type: inuse_space
Time: May 22, 2018 at 3:36pm (CST)
Showing nodes accounting for 1.16MB, 100% of 1.16MB total
      flat  flat%   sum%        cum   cum%
    1.16MB   100%   100%     1.16MB   100%  runtime/pprof.StartCPUProfile
         0     0%   100%     1.16MB   100%  main.main
         0     0%   100%     1.16MB   100%  runtime.main

pprof 交互模式分析

$ go tool pprof testTB.test cpu.out
输出:
File: testTB.test
Type: cpu
Time: May 22, 2018 at 3:08pm (CST)
Duration: 906.10ms, Total samples = 670ms (73.94%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
输出:
Showing nodes accounting for 670ms, 100% of 670ms total
      flat  flat%   sum%        cum   cum%
     670ms   100%   100%      670ms   100%  _/Users/golang_learning/testTB.Benchmark
         0     0%   100%      670ms   100%  testing.(*B).launch
         0     0%   100%      670ms   100%  testing.(*B).runN
(pprof) quit

以上性能指标含义:

  • 函数本地采样数量(不包含其调用的其他函数)
  • 函数本地采样数量所占百分比
  • 前几个函数(包括当前函数)本地采样总和所占百分比
  • 函数(包括其调用的函数)采样总数量
  • 函数采样总数量所占百分比

pprof 交互模式命令:

  • top、top10: 显示前几条信息;
  • web:以 svg 文件展示。

pdf 或者 svg 分析

$ go tool pprof -svg cpu.out > cpu.svg
$ go tool pprof -pdf cpu.out > cpu.pdf
$ ls(以上命令生成cpu.pdf和cpu.svg文件)
add_test.go   cpu.out    cpu.pdf        cpu.svg     testTB.test

打开 cpu.pdf 或者 cpu.svg 文件

代码生成测试数据文件

用 runtime/pprof 包生成 cpu 和 mem 文件

// filename: pprof.go
package main
import (
    "os"
    "runtime/pprof"
)

func main() {
    w, _ := os.Create("cpu.out")
    defer w.Close()
    pprof.StartCPUProfile(w)
    defer pprof.StopCPUProfile()

    w2, _ := os.Create("mem.out")
    defer w2.Close()
    defer pprof.WriteHeapProfile(w2)

    Sum(3, 5)

}

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

编译并执行以上文件

$ go build pprof.go
$ ./pprof
$ ls(./pprof命令生成cpu.out和mem.out文件)
cpu.out     mem.out     pprof       pprof.go

生成 pdf 文件

$ go tool pprof -pdf cpu.out > cpu.pdf
$ go tool pprof -pdf mem.out > mem.pdf

net/http/pprof

若是测量 http server 的性能,则需要使用 net/http/pprof 包。只需要在源文件中加入代码

import (
    _ "net/http/pprof"
)

cpu 分析

启动 http server,然后在浏览器中访问链接:http://localhost:[port]/debug/pprof/就能看到 prof 信息了:

若要生成 CPU 状态分析图,可使用以下命令:

$ go tool pprof http://localhost:port/debug/pprof/profile

就会进入 30 秒的 profile 收集时间,在这段事件内向服务器连续发送多次请求,尽量让 cpu 占用性能产生数据。

$ go tool pprof http://localhost:8080/debug/pprof/profile
输出:
Fetching profile over HTTP from http://localhost:8080/debug/pprof/profile
// 这里会阻塞30s收集profile,在这段时间应多发请求
Saved profile in /Users/pprof/pprof.samples.cpu.002.pb.gz
Type: cpu
Time: May 22, 2018 at 7:16pm (CST)
Duration: 30s, Total samples = 330ms ( 1.10%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top10
输出:(前10条信息)
Showing nodes accounting for 330ms, 100% of 330ms total
Showing top 10 nodes out of 39
      flat  flat%   sum%        cum   cum%
     100ms 30.30% 30.30%      100ms 30.30%  runtime.mach_semaphore_signal
      60ms 18.18% 48.48%       60ms 18.18%  runtime.mach_semaphore_timedwait
      60ms 18.18% 66.67%       60ms 18.18%  runtime.mach_semaphore_wait
      ... ...
(pprof) web
// 在浏览器中以svg文件的方式展示cpu占用图

内存分析

启动服务器,访问链接http://localhost:port/debug/pprof/heap,就会自动下载 heap 文件,调用以下命令,进入 pprof 交互模式

$ go tool pprof heap
Main binary filename not available.
Type: inuse_space
Time: May 24, 2018 at 11:30pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top5
Showing nodes accounting for 62.02MB, 98.20% of 63.16MB total
Showing top 5 nodes out of 26
      flat  flat%   sum%        cum   cum%
   21.67MB 34.31% 34.31%    21.67MB 34.31%  bytes.makeSlice
   20.50MB 32.46% 66.77%    20.50MB 32.46%  reflect.unsafe_New
      15MB 23.75% 90.52%       15MB 23.75%  github.com/golang/protobuf/proto.(*word32Slice).Append
    2.85MB  4.51% 95.03%     2.85MB  4.51%  github.com/golang/protobuf/proto.(*structPointerSlice).Append
       2MB  3.17% 98.20%        2MB  3.17%  github.com/golang/protobuf/proto.word32_Set
(pprof) web

原文地址:https://www.cnblogs.com/zhichaoma/p/12510031.html

时间: 2024-10-15 08:17:20

Golang 单元测试与性能测试的相关文章

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

单元测试代码: ackage test import ( // "fmt" "testing" ) func Test_FlowControl(t *testing.T) { var x int64 = 10 if x == 10 { // fmt.Println("x is 10") t.Log("x is 10") } else { // fmt.Println("x is not 10") t.Log

golang 单元测试&amp;&amp;性能测试

一:单元测试 1.为什么要做单元测试和性能测试 减少bug 快速定位bug 减少调试时间 提高代码质量 2.golang的单元测试 单元测试代码的go文件必须以_test.go结尾 单元测试的函数名必须以Test开头,是可导出公开的函数 测试函数的签名必须接收一个指向testing.T类型的指针,并且不能返回任何值 3.golang单元测试组 有好几个不同的输入以及输出组成的一组单元测试 4.测试覆盖率 go test -cover 直接输出覆盖率 go test -run TestAll 指定

golang 单元测试

单元测试是质量保证十分重要的一环,好的单元测试不仅能及时地发现问题,更能够方便地调试,提高生产效率,所以很多人认为写单元测试是需要额外的时间,会降低生产效率,是对单元测试最大的偏见和误解 go 语言原生支持了单元测试,使用上非常简单,测试代码只需要放到以 _test.go 结尾的文件中即可.golang的测试分为单元测试和性能测试,单元测试的测试用例以 Test 开头,性能测试以 Benchmark 开头 举个例子 实现排列组合函数对应的单元测试和性能测试 实现排列组合函数 // combina

ARTS-S golang单元测试

golang单元测试 在$GOPATH的src目录下建目录demo_unittest 在目录demo_unittest下建文件calc.go,内容如下: package demo_unittest func Add(a, b int) int { return a + b } func Sub(a, b int) int { return a - b } func Mul(a, b int) int { return a * b } func Div(a, b int) int { return

入门级----黑盒测试、白盒测试、手工测试、自动化测试、探索性测试、单元测试、性能测试、数据库性能、压力测试、安全性测试、SQL注入、缓冲区溢出、环境测试

黑盒测试 黑盒测试把产品软件当成是一个黑箱子,只有出口和入口,测试过程中只要知道往黑盒中输入什么东西,知道黑盒会出来什么结果就可以了,不需要了解黑箱子里面是如果做的. 即测试人员不用费神去理解软件里面的具体构成和原理,只要像用户一样看待产品就可以了. 例如银行转账功能,不需要知道转账的具体实现代码是怎样工作的,只需要把自己想象成各种类型的用户,模拟多种转账情况看系统是否能正常转账即可. 但是仅仅像用户一样去测试又是不够的.如果只做黑盒测试,必然是存在一定的风险的. 例如某个安全性较高的软件系统,

系统测试——代码质量检查、单元测试、性能测试、自动构建、项目管理

根据软件开发的过程和由细节到外部的顺序,将软件测试划分为5个阶段: 1)代码质量检查:对代码的格式.潜在的Bug进行检查,常用的工具有Checkstyle.PMD.FindBugs: 2)单元测试:对代码的功能进行测试,常用的工具有JUnit.EasyMock: 3)性能测试:对代码的性能进行测试,常用的工具有JMeter.Profiler: 4)自动构建:对代码进行自动构建和持续集成测试.部署,常用的工具有Ant.Maven.CruiseControl: 5)项目管理:对软件测试中的Bug进行

golang单元测试

使用testing进行单元测试 golang的测试库testing 测试文件与被测试文件在同一个包中 测试文件名为被测试文件名(去后缀)_test.go 测试用例函数以Test开头,TestFunc1(t *testing.T) 一个测试用例文件中可以有多个测试用例函数 在测试用例函数中调用被测试函数,根据函数返回结果与预期的正确结果的比较, 判断函数是否正确.t.Log输出日志,t.Fatal输出错误信息. 执行测试文件的方式 执行全部测试文件中全部函数 go test 如果需要输出日志信息g

WebApi管理和性能测试工具WebApiBenchmarks

说到WebApi管理和测试工具其实已经非常多的了,Postman.Swagger等在管理和维护上都非常出色:在性能测试方面也有不少的工具如:wrk,bombardier,http_load和ab等等.不过这些工具都具有单一性,管理和维护好的在性能测试上比较低效,对于性能测试好的在管理和维护上不理想!以下主要介绍一款基于dotnet core开发的WebApiBenchmarks工具,这个工具可以对webapi进行管理和维护并提供高效的性能测试能力,接下来来先预览一下这个小工具再进行详细介绍. 功

go语言系统-从文件操作到单元测试

目录 文件操作 输入流和输出流 打开文件和关闭文件 使用的函数和方法 案例演示 读文件操作应用案例 写文件操作应用案例 判断文件是否存在 文件编程应用实例 拷贝文件 统计英文.数字.空格和其它字符数量 命令行参数 举例说明 flag包用来解析命令行参数 Json Json基本介绍 应用场景 Json数据格式说明 Jsnon数据在线解析 Json的序列化 应用案例 Json的反序列化 应用案例 单元测试 先看一个需求 传统的方法 传统方法的缺点分析 单元测试 基本介绍 快速入门 单元测试快速入门总