- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Go语言单元测试超详细解析由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言
平时根据需求写代码.人工进行测试往往不会面面俱到,还会因为需求的改变繁琐的进行测试 通过完成一个测试函数,可以大大简化测试的步骤,并且在需求该变的时候只需要改变一下测试的输入与期望 。
Benchmark
主要测试函数的性能Example
为文档提示示例文档
①测试函数 。
go test -cover
go test -cover -coverprofile=c.out
(将测试的结果存入文件c.out)go tool cover -html=c.out
可以打开文件,显示哪些代码没有执行②基准测试 。
(1)基准测试函数需要注意的点 。
进行基准测试时往往是对函数的算法进行测验,有时后一个算法在测试数据的基量不同时测试出的效果会不同我们需要对不同数量级的样本进行测试的时候。可以自己写一个盒子作为跳板,测试什么数量级的数据就只进行当前数量级的测试 。
测试的时候命令为:go test -bench=.(将所有的跳板函数均执行一遍)或者=特定函数进行特定函数测试-benchtime=time (在被测试函数在基准函数默认的时间内执行不完时可以拿这个参数进行时间的扩充)在进行基准函数测试的时候,可能需要进行一些前置工作,如果感觉前置工作浪费时间可以使用 b.ResetTimer()对计时器进行重置 。
(2)基准测试代码 。
测试函数代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//
文件名 subStr_test.go
package main
import
(
"reflect"
"testing"
)
func BenchmarkSubStr(b *testing.B) {
for
i := 0; i < b.N; i++ {
res := subStr(
"qwe:qw:es:wqe"
,
":"
)
if
!reflect.DeepEqual(res, []string{
"qwe"
,
"qw"
,
"es"
,
"wqe"
}) {
b.Errorf(
"不匹配"
)
}
}
}
func benchmarkFib(b *testing.B, n int) {
for
i := 0; i < b.N; i++ {
Fib(n)
}
}
func BenchmarkFib5(b *testing.B) { benchmarkFib(b, 5) }
func BenchmarkFib10(b *testing.B) { benchmarkFib(b, 10) }
func BenchmarkFib15(b *testing.B) { benchmarkFib(b, 15) }
func BenchmarkFib20(b *testing.B) { benchmarkFib(b, 20) }
|
被测函数代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
//
文件名 subStr.go
package main
import
(
"fmt"
"strings"
)
func subStr(str, stre string) []string {
index := strings.Index(str, stre)
var theSub []string
for
index >= 0 {
//
先将分隔符前面的数据进行保存
temp := str[:index]
//
将字符串往后移
str = str[index+1:]
//
重新获取下标
index = strings.Index(str, stre)
if
temp !=
""
{
theSub = append(theSub, temp)
}
else
{
continue
}
}
theSub = append(theSub, str)
return
theSub[:]
}
//
菲薄那契数列
func Fib(n int) int {
if
n < 2 {
return
n
}
return
Fib(n-1) + Fib(n-2)
}
func main() {
fmt
.Println(subStr(
"q:w:ec:wer:cd:scn:cj:c:is:icc:cin:si"
,
":"
))
fmt
.Printf(
"%#v\n"
, subStr(
"q:w:ec:wer:cd:scn:cj:c:is:icc:cin:si"
,
":"
))
fmt
.Println(123)
}
|
将以上两个文件放在同一目录下,执行测试命令 go test 。
得到测试结果
goos: windows goarch: amd64 cpu: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz BenchmarkSubStr-8 1213681 1012 ns/op 352 B/op 14 allocs/op PASS ok _/d_/Go语言学习笔记/go语言语法部分/go语言进阶语法/8.单元测试/基准测试 2.410s 。
测试函数如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package main
import
(
"reflect"
"testing"
)
type
testS struct {
str string
ste string
want []string
}
//
进行组测试,批量进行测试,如果有哪个地方不满足则进行异常抛出
//
func TestSubStr(t *testing.T) {
//
testMap := map[string]testS{
//
"case_1"
: {
"123:eqwe:123"
,
":"
, []string{
"123"
,
"eqwe"
,
"123"
}},
//
"case_2"
: {
"13:eqwe3:1@23"
,
"3:"
, []string{
"1"
,
"eqwe"
,
"1@23"
}},
//
"case_3"
: {
"12@3@:@eq@we@:1@23"
,
"@:"
, []string{
"12@3"
,
"@eq@we"
,
"1@23"
}},
//
"case_4"
: {
"123:eq@we:1@2@3"
,
"q@"
, []string{
"123:e"
,
"we:1@2@3"
}},
//
"case_5"
: {
"123:eqwe:123"
,
"2"
, []string{
"1"
,
"3:eqwe:1"
,
"3"
}},
//
"case_6"
: {
"123:eqwe:123"
,
"eqwe"
, []string{
"123:"
,
":123"
}},
//
}
//
for
k,
v
:= range testMap {
//
res := subStr(
v
.str,
v
.ste)
//
if
!reflect.DeepEqual(res,
v
.want) {
//
t.Errorf(
"%v want:%#v got:%#v"
, k,
v
.want, res)
//
}
//
}
//
}
//
进行子测试,可以针对某个子样本进行测试
func TestSubStr(t *testing.T) {
testMap := map[string]testS{
"case_1"
: {
"13:eqwe:123"
,
":"
, []string{
"123"
,
"eqwe"
,
"123"
}},
"case_2"
: {
"3:eqwe3:1@23"
,
"3:"
, []string{
"1"
,
"eqwe"
,
"1@23"
}},
"case_3"
: {
"2@3@:@eq@we@:1@23"
,
"@:"
, []string{
"12@3"
,
"@eq@we"
,
"1@23"
}},
"case_4"
: {
"123:eq@we:1@2@3"
,
"q@"
, []string{
"123:e"
,
"we:1@2@3"
}},
"case_5"
: {
"23:eqwe:123"
,
"2"
, []string{
"1"
,
"3:eqwe:1"
,
"3"
}},
"case_6"
: {
"123:eqwe:123"
,
"eqwe"
, []string{
"123:"
,
":123"
}},
}
for
k,
v
:= range testMap {
t.Run(k, func(t *testing.T) {
res := subStr(
v
.str,
v
.ste)
if
!reflect.DeepEqual(res,
v
.want) {
t.Errorf(
"want:%#v got:%#v"
,
v
.want, res)
}
})
}
}
|
待测函数如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package main
import
(
"fmt"
"strings"
)
func subStr(str, stre string) []string {
index := strings.Index(str, stre)
var theSub []string
for
index >= 0 {
//
先将分隔符前面的数据进行保存
temp := str[:index]
//
将字符串往后移
str = str[index+len(stre):]
//
重新获取下标
index = strings.Index(str, stre)
if
temp !=
""
{
theSub = append(theSub, temp)
}
else
{
continue
}
}
theSub = append(theSub, str)
return
theSub[:]
}
func main() {
fmt
.Println(subStr(
"q:w:ec:wer:cd:scn:cj:c:is:icc:cin:si"
,
":c"
))
fmt
.Printf(
"%#v\n"
, subStr(
"q:w:ec:wer:cd:scn:cj:c:is:icc:cin:si"
,
":"
))
fmt
.Println(123)
}
|
(1).组测试结果分析及命令:
go test
--- FAIL: TestSubStr (0.00s) --- FAIL: TestSubStr/case_1 (0.00s) subStr_test.go:46: want:[]string{"123", "eqwe", "123"} got:[]string{"13", "eqwe", "123"} --- FAIL: TestSubStr/case_2 (0.00s) subStr_test.go:46: want:[]string{"1", "eqwe", "1@23"} got:[]string{"eqwe", "1@23"} --- FAIL: TestSubStr/case_3 (0.00s) subStr_test.go:46: want:[]string{"12@3", "@eq@we", "1@23"} got:[]string{"2@3", "@eq@we", "1@23"} --- FAIL: TestSubStr/case_5 (0.00s) subStr_test.go:46: want:[]string{"1", "3:eqwe:1", "3"} got:[]string{"3:eqwe:1", "3"} FAIL exit status 1 FAIL _/D_/Go语言学习笔记/go语言语法部分/go语言进阶语法/8.单元测试/组测试与子测试 0.155s 。
(2).子测试结果分析及命令:
go test -v -run=TestSubStr/case_1
(等号后面跟的是上面组测试失败案例FAIL后面的目录)=== RUN TestSubStr === RUN TestSubStr/case_1 subStr_test.go:46: want:[]string{"123", "eqwe", "123"} got:[]string{"13", "eqwe", "123"} --- FAIL: TestSubStr (0.00s) --- FAIL: TestSubStr/case_1 (0.00s) FAIL exit status 1 FAIL _/D_/Go语言学习笔记/go语言语法部分/go语言进阶语法/8.单元测试/组测试与子测试 0.186s 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
(1)os.Args
package main1
import
(
"fmt"
"os"
)
func main() {
//
os.Args可以在执行函数的时候传递参数,但是对于-name=xxx没有办法将其解析
if
os.Args != nil {
for
index, temp := range os.Args {
fmt
.Println(
"第"
, index+1,
"个参数是:"
, temp)
}
}
fmt
.Println(
"hello"
)
}
|
(2)flag.Args 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package main
import
(
"flag"
"fmt"
"time"
)
func main() {
//
第一个参数为对应的参数,第二个参数为默认值,第三个参数为提示
//
返回的是对应类型的指针
//
name := flag.String(
"name"
,
"Tom"
,
"输入name"
)
//
sex := flag.Bool(
"sex"
,
true
,
"是不是男性"
)
//
age := flag.Int(
"age"
, 10,
"年龄"
)
//
flag.Parse()
//
fmt
.Println(*name, *sex, *age)
var name string
var age int
var sex bool
flag.StringVar(&name,
"name"
,
"Tom"
,
"输入name"
)
flag.BoolVar(&sex,
"sex"
,
true
,
"是不是男性"
)
flag.IntVar(&age,
"age"
, 10,
"年龄"
)
tim := flag.Duration(
"time"
,
time
.Hour,
"时间"
)
//
将输入的数据进行解析,不使用这句话的话不能获取到name sex age等属性对应的值
flag.Parse()
fmt
.Println(name, sex, age, *tim)
fmt
.Println(flag.Args())
//
以切片的方式返回命令行之外的其他参数
fmt
.Println(flag.NArg())
//
返回命令行之外的其他参数的个数
fmt
.Println(flag.NFlag())
//
返回使用命令行的参数的个数
}
|
pprof调试工具进行调试,主要看待测模块在内存于时间上的效益调试的时候只会显示耗费时间空间较多的代码段. 。
生成调试代码块的文件:go run xx.exe -cpu.... 使用go语言工具查看代码块所存在的问题:go tool pprof cpu.pprof 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
package main
import
(
"flag"
"fmt"
"os"
"runtime/pprof"
"time"
)
//
一段有问题的代码
func logicCode() {
var c chan int
for
{
select
{
case
v
:= <-c:
fmt
.Printf(
"recv from chan, value:%v\n"
,
v
)
default:
}
}
}
func main() {
var isCPUPprof bool
var isMemPprof bool
//
获取接收到的参数
flag.BoolVar(&isCPUPprof,
"cpu"
,
false
,
"turn cpu pprof on"
)
flag.BoolVar(&isMemPprof,
"mem"
,
false
,
"turn mem pprof on"
)
flag.Parse()
//
判断进行什么测试,然后执行分支,并将信息保存到相应的文件内。
if
isCPUPprof {
file
, err := os.Create(
"./cpu.pprof"
)
if
err != nil {
fmt
.Printf(
"create cpu pprof failed, err:%v\n"
, err)
return
}
pprof.StartCPUProfile(
file
)
defer pprof.StopCPUProfile()
}
for
i := 0; i < 8; i++ {
go logicCode()
}
time
.Sleep(20 *
time
.Second)
if
isMemPprof {
file
, err := os.Create(
"./mem.pprof"
)
if
err != nil {
fmt
.Printf(
"create mem pprof failed, err:%v\n"
, err)
return
}
pprof.WriteHeapProfile(
file
)
file
.Close()
}
}
|
总结
这里对常用的测试函数,子测试进行了详细的讲解,对于pprof参数调优仅仅做了个介绍,可以根据自己的兴趣在网上找一部分pprof的例子深入学习,进行自动化测试非常方便.
到此这篇关于Go语言单元测试超详细解析的文章就介绍到这了,更多相关Go语言单元测试内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/apple_51931783/article/details/122563019 。
最后此篇关于Go语言单元测试超详细解析的文章就讲到这里了,如果你想了解更多关于Go语言单元测试超详细解析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我一直在使用 AJAX 从我正在创建的网络服务中解析 JSON 数组时遇到问题。我的前端是一个简单的 ajax 和 jquery 组合,用于显示从我正在创建的网络服务返回的结果。 尽管知道我的数据库查
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我在尝试运行 Android 应用程序时遇到问题并收到以下错误 java.lang.NoClassDefFoundError: com.parse.Parse 当我尝试运行该应用时。 最佳答案 在这
有什么办法可以防止etree在解析HTML内容时解析HTML实体吗? html = etree.HTML('&') html.find('.//body').text 这给了我 '&' 但我想
我有一个有点疯狂的例子,但对于那些 JavaScript 函数作用域专家来说,它看起来是一个很好的练习: (function (global) { // our module number one
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 8 年前。 Improve th
我需要编写一个脚本来获取链接并解析链接页面的 HTML 以提取标题和其他一些数据,例如可能是简短的描述,就像您链接到 Facebook 上的内容一样。 当用户向站点添加链接时将调用它,因此在客户端启动
在 VS Code 中本地开发时,包解析为 C:/Users//AppData/Local/Microsoft/TypeScript/3.5/node_modules/@types//index而不是
我在将 json 从 php 解析为 javascript 时遇到问题 这是我的示例代码: //function MethodAjax = function (wsFile, param) {
我在将 json 从 php 解析为 javascript 时遇到问题 这是我的示例代码: //function MethodAjax = function (wsFile, param) {
我被赋予了将一种语言“翻译”成另一种语言的工作。对于使用正则表达式的简单逐行方法来说,源代码过于灵活(复杂)。我在哪里可以了解更多关于词法分析和解析器的信息? 最佳答案 如果你想对这个主题产生“情绪化
您好,我在解析此文本时遇到问题 { { { {[system1];1;1;0.612509325}; {[system2];1;
我正在为 adobe after effects 在 extendscript 中编写一些代码,最终变成了 javascript。 我有一个数组,我想只搜索单词“assemble”并返回整个 jc3_
我有这段代码: $(document).ready(function() { // }); 问题:FB_RequireFeatures block 外部的代码先于其内部的代码执行。因此 who
背景: netcore项目中有些服务是在通过中间件来通信的,比如orleans组件。它里面服务和客户端会指定网关和端口,我们只需要开放客户端给外界,服务端关闭端口。相当于去掉host,这样省掉了些
1.首先贴上我试验成功的代码 复制代码 代码如下: protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
什么是 XML? XML 指可扩展标记语言(eXtensible Markup Language),标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。 你可以通过本站学习 X
【PHP代码】 复制代码 代码如下: $stmt = mssql_init('P__Global_Test', $conn) or die("initialize sto
在SQL查询分析器执行以下代码就可以了。 复制代码代码如下: declare @t varchar(255),@c varchar(255) declare table_cursor curs
前言 最近练习了一些前端算法题,现在做个总结,以下题目都是个人写法,并不是标准答案,如有错误欢迎指出,有对某道题有新的想法的友友也可以在评论区发表想法,互相学习🤭 题目 题目一: 二维数组中的
我是一名优秀的程序员,十分优秀!