In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-12 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
Xiaobian to share with you the example analysis of Go language unit testing, I believe most people still do not know how, so share this article for everyone's reference, I hope you have a lot of harvest after reading this article, let's go to understand it together!
1. Unit test classification and its concept 1. Basic classification
Test function prefix Test is mainly used to Test whether some logical behavior of the program is correct
Benchmark function name prefix Benchmark primary test function performance
Example Functions The prefix name of a function is Example for documentation Tips Example documentation
2. Detailed unit test classification
① Test function
Basic tests of functions
group test of function
subtest of function
Test function coverage (i.e. how much code is used to execute the function under test)
When testing, ensure that the coverage rate of the tested function is 100%, and the coverage rate of the test function is more than 60%, otherwise most of the code written will not be used and needs to be optimized.
Go Test -Cover
②go test -cover -coverprofile=c.out(store the test results in the file c.out)
Then use go tool cover -html=c.out to open the file and show what code has not been executed
② Benchmark test
What does benchmark function test do: benchmark function will customize a time period for executing code, if the code is concise, the number of executions of the function under test needs to be multiplied (until the benchmark function is expected, and then count the total number of rounds executed, and how much time each round takes)
When executing a benchmark function, first write the benchmark function
The parameters of the benchmark function are: *testing.B corresponding pointer variable
A loop is performed inside the test function, and the termination condition of the loop is b.N.
II. Detailed description of each test in combination with code 1. Benchmark test
(1) Benchmark function points to note
Benchmarking is often a test of the algorithm of the function, sometimes the latter algorithm in the test data base at the same time the test results will be different We need to test samples of different orders of magnitude. You can write your own box as a springboard to test only the current order of magnitude of data
The test command is: go test -bench=. (All springboard functions are executed once) or = specific function for specific function test-benchtime=time (this parameter can be used to extend the time when the function under test cannot be executed within the default time of the benchmark function) When performing benchmark function test, some preliminary work may be required. If you feel that the preliminary work wastes time, you can use b.ResetTimer() to reset the timer.
(2) Benchmark code
The test function code is as follows:
//filename subStr_test.gopackage mainimport ( "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) } 被测函数代码如下: //文件名 subStr.gopackage mainimport ( "fmt" "strings")func subStr(str, stre string) []string { index := strings.Index(str, stre) var theSub []string for index >= 0 { //save the data before the delimiter first temp := str[:index] //Move string backward str = str[index+1:] //retrieve subscript index = strings.Index(str, stre) if temp != "" { theSub = append(theSub, temp) } else { continue } } theSub = append(theSub, str) return theSub[:]}//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 2.组测试与子测试 对于一个函数的测试,不仅仅是一组测试用例,所以我们需要写测试组, 对一个函数进行测试,测试的时候一般用集合键值对构成,每一个键对应一组测试数据 进行组测试的时候可能会有个别的组出错,所以使用子测试可以对某个案例进行单独测试这就是测试组与子测试的产生背景 测试函数如下: package mainimport ( "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) } }) }} 待测函数如下: package mainimport ( "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).子测试结果分析及命令:
例如单独测试case_1,使用的命令为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
三、pprof调试工具1.对主函数进行传参(1)os.Argspackage main1import ( "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
相对于os.Args来说,flag.Args使用起来更加方便
package mainimport ( "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()) //返回使用命令行的参数的个数}2.pprof性能调优
pprof调试工具进行调试,主要看待测模块在内存于时间上的效益调试的时候只会显示耗费时间空间较多的代码段.
生成调试代码块的文件:go run xx.exe -cpu....
使用go语言工具查看代码块所存在的问题:go tool pprof cpu.pprof
package mainimport ( "flag" "fmt" "os" "runtime/pprof" "time")// 一段有问题的代码func logicCode() { var c chan int for { select { case v :=
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.