0


Golang 编写测试用例(单元测试、压力测试等)最新教程,细到极致

   Hello,各位小伙伴,我们今天来学习一下go的测试,希望给各位一点点小小的帮助
   有过编程基础的,或者工作的了,应该知道,一个软件的质量,三分靠开发,七分靠测试。如果没有及时发现存在的问题,将会给这个公司带来巨大的经济损失。老哥因为转Go了,所以非常有必要学习一个Go 相关的测试。
  话不多说,开始学习吧。

1、在go语言中,一共有4种测试,参考文档,https://pkg.go.dev/testing
类型格式作用传入参数单元测试函数的前缀名为Test一个函数正常测试功能t *testing.T基准(压力测试)函数的前缀名为Benchmark通过cpu和内存,并发测试程序的性能b *testing.B实例测试函数的前缀名为Example给测试人员提供实例文档m *testing.M模糊(随机) 测试函数的前缀名为Fuzz生成一个随机测试用例去覆盖可能人为测不到的地方f *testing.F
2、然后我们先来讲第一种,

  1. 单元测试

,然后单元测试有多种写法,还支持钩子函数(我们可以在测试开始前和测试后,增加一些业务逻辑),新建一个文件

  1. calc.go
  1. package main
  2. func Add(a int, b int)int{return a + b
  3. }
  4. func Mul(a int, b int)int{return a * b
  5. }

3、然后是测试文件,在go语言中,所有测试用例的文件命名用_test结尾,新建一个测试文件

  1. calc_test.go
  1. package main
  2. func TestAdd(t *testing.T){if value :=Add(1,2); value !=3{
  3. t.Errorf("1+2 expected be 3, but %d got", value)}if value :=Mul(1,2); value !=2{
  4. t.Errorf("1*2 expected be 2, but %d got", value)}}

点击这个绿色图标,就可以开始测试了

在这里插入图片描述
除了点击绿色图标以外,我们也可以换一种方式,到当前文件夹下,打开Goland控制终端,输入下面的命令,它会执行当前文件夹所有的测试文件,并且输出详细的信息

  1. PS D:\Project\Go_Project\testCobraPlus> go test -v

3A、单元测试如果有多个用例的话,可以试试嵌套测试,它可以分开测试

  1. // 嵌套测试
  2. func TestMul(t *testing.T){
  3. t.Run("pos",func(t *testing.T){ifMul(2,3)!=6{
  4. t.Fatal("expected to get 6,but fail...")}})
  5. t.Run("neg",func(t *testing.T){ifMul(2,-3)!=-6{
  6. t.Fatal("expected to get -6,but fail...")}})}

点击第一个,会测试全部用例,点击第二个或者第三个,它会测试你点击的那一个

在这里插入图片描述
5、单元测试第三种形式,也是k8s用的测试形式,它这种用要给切片存放多条数据,可以一次性测试多个值,推荐使用

  1. func TestMul2(t *testing.T){
  2. cases :=[]struct{
  3. Name string
  4. A, B, Expected int}{{"pos",2,3,6},{"neg",2,-3,-6},{"zero",2,0,0},}for _, c := range cases {
  5. t.Run(c.Name,func(t *testing.T){if value :=Mul(c.A, c.B); value != c.Expected {
  6. t.Fatalf("%d * %d expected %d,but %d got", c.A, c.B, c.Expected, value)}})}}

6、单元测试钩子,如果我们加了以下几行代码,那么当我们点击了3、3A、5任何一个测试用例,以下代码就会执行

  1. func before(){
  2. fmt.Println("Before all tests...")}
  3. func after(){
  4. fmt.Println("After all tests...")}
  5. func TestMain(m *testing.M){before()
  6. code := m.Run()after()
  7. os.Exit(code)}

7、单元测试http,如果我们需要测试发送数据或者接收数据,可以采用httptest 测试库进行测试
新建一个测试文件

  1. network_test.go
  1. package main
  2. import("io""net/http""net/http/httptest""testing")
  3. func helloHandler(w http.ResponseWriter, r *http.Request){
  4. w.Write([]byte("hello baidu"))}
  5. func TestConn(t *testing.T){
  6. req := httptest.NewRequest("GET","https://www.baidu.com/", nil)
  7. w := httptest.NewRecorder()helloHandler(w, req)
  8. bytes, _ := io.ReadAll(w.Result().Body)ifstring(bytes)!="hello baidu"{
  9. t.Fatal("expected hello baidu,but got",string(bytes))}}

在这里插入图片描述
8、然后是基准(压力)测试,这里需要说明一下,压力测试和单元测试最大的区别是单元测试它只执行一次,成功一次就算成功,而压力测试需要执行多次,任何一次不成功都算失败

  1. package main
  2. import("bytes""testing")
  3. func Benchmark_Add(b *testing.B){
  4. var n int//b.N 是基准测试框架提供的,表示循环的次数,没有具体的限制for i :=0; i < b.N; i++{
  5. n++}}
  6. func BenchmarkConcatStringByAdd(b *testing.B){//有些测试需要一定的启动和初始化时间,如果从 Benchmark() 函数开始计时会很大程度上影响测试结果的精准性。//testing.B 提供了一系列的方法可以方便地控制计时器,从而让计时器只在需要的区间进行测试
  7. elem :=[]string{"1","2","3","4","5"}
  8. b.ResetTimer()for i :=0; i < b.N; i++{
  9. ret :=""for _, v := range elem {
  10. ret += v
  11. }}
  12. b.StopTimer()}
  13. func BenchmarkConcatStringByByteBuffer(b *testing.B){
  14. elems :=[]string{"1","2","3","4","5"}
  15. b.ResetTimer()for i :=0; i < b.N; i++{
  16. var buf bytes.Buffer
  17. for _, elem := range elems {
  18. buf.WriteString(elem)}}
  19. b.StopTimer()}

同样,我们也可以在goland控制终端,查看执行信息,终端操作会执行当前文件夹的所有压力测试用例

  1. goos: windows

运行在哪个操作系统上

  1. goarch: amd64

运行操作系统的架构

  1. cpu: 12th Gen Intel(R) Core(TM) i7-12700KF

cpu相关信息

  1. Benchmark_Add-20 1000000000 0.1053 ns/op

Benchmark_Add我们测试的方法 20表示20个逻辑cpu,1000000000 表示执行了1000000000 次,最后一次是每一次执行需要0.1053ns

  1. PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -v -bench="." benchmark_test.go
  2. goos: windows
  3. goarch: amd64
  4. cpu:12th Gen Intel(R)Core(TM) i7-12700KF
  5. Benchmark_Add
  6. Benchmark_Add-2010000000000.1053 ns/op
  7. BenchmarkConcatStringByAdd
  8. BenchmarkConcatStringByAdd-202075894657.88 ns/op
  9. BenchmarkConcatStringByByteBuffer
  10. BenchmarkConcatStringByByteBuffer-204013445028.70 ns/op
  11. PASS
  12. ok command-line-arguments 2.694s
  13. PS D:\Project\Go_Project\testCobraPlus\benchmark>

9、压力测试自定义测试时间,也就是测试多少秒,默认是测试1秒的压测情况

  1. PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -v -bench="."-benchtime=5s benchmark_test.go
  2. goos: windows
  3. goarch: amd64
  4. cpu:12th Gen Intel(R)Core(TM) i7-12700KF
  5. Benchmark_Add
  6. Benchmark_Add-2010000000000.1051 ns/op
  7. BenchmarkConcatStringByAdd
  8. BenchmarkConcatStringByAdd-209868859258.19 ns/op
  9. BenchmarkConcatStringByByteBuffer
  10. BenchmarkConcatStringByByteBuffer-2021437558228.14 ns/op
  11. PASS
  12. ok command-line-arguments 14.921s

10、压力测试查看内存分配了多少,如

-bench=Add 指定尾缀是Add方法,都会执行
-benchmem 查看内存分配多少,比如下面一个方法,16 B/op 表示一次调用需要分配16个字节, 4 allocs/op 表示每一次调用有4次分配

  1. PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -v -bench=Add -benchmem benchmark_test.go
  2. goos: windows
  3. goarch: amd64
  4. cpu:12th Gen Intel(R)Core(TM) i7-12700KF
  5. Benchmark_Add
  6. Benchmark_Add-2010000000000.1060 ns/op 0 B/op
  7. 0 allocs/op
  8. BenchmarkConcatStringByAdd
  9. BenchmarkConcatStringByAdd-201973801057.19 ns/op 16 B/op
  10. 4 allocs/op
  11. PASS
  12. ok command-line-arguments 1.439s

11、实例测试,这个测试有点简单,写个 //Output注释,然后后面是期望输出的结果,如果是一致的,测试通过,否则测试失败

  1. func Hello() string {return"Hello World"}//Output 需要和上面打印的内容一致,否则测试失败
  2. func ExampleHello(){
  3. fmt.Println(Hello())// Output: Hello World}
  4. func TestMain(m *testing.M){
  5. fmt.Println("Before...")
  6. code := m.Run()
  7. fmt.Println("End...")
  8. os.Exit(code)}

和上面一样,我们也可以在控制台终端,进行实例测试

  1. PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -v -run="ExampleHello"
  2. Before...=== RUN ExampleHello
  3. --- PASS:ExampleHello(0.00s)
  4. PASS
  5. End...
  6. ok testCobraPlus/benchmark 0.125s

12、模糊测试,这是go1.18新推出的测试用例,如果我们没有指定参数,系统会随机填入参数进行测试

  1. func FuzzStrToNum(f *testing.F){
  2. f.Fuzz(func(t *testing.T, a string){
  3. b, _ := strconv.ParseInt(a,10,64)
  4. fmt.Printf("%d\n", b)})}
  1. func FuzzDivision(f *testing.F){
  2. f.Fuzz(func(t *testing.T, a, b int){
  3. fmt.Println(a / b)})}
  1. //我们可以在模糊测试中,自己定义参数进去
  2. func FuzzHello(f *testing.F){
  3. f.Add(1)
  4. f.Fuzz(func(t *testing.T, num int){if num !=6{
  5. t.Errorf("expected 6,but got %d", num)}})}

模糊测试同样支持控制台输入,但是同一个文件只能有一个模糊函数测试

  1. PS D:\Project\Go_Project\testCobraPlus\benchmark> go test -fuzztime 10s -fuzz .

13、最后,各位小伙伴,麻烦给老哥一个点赞、关注、收藏三连好吗,你的支持是老哥更新最大的动力,谢谢!


本文转载自: https://blog.csdn.net/gubeichengxuyuan/article/details/126826813
版权归原作者 Jesscia ^_^ 所有, 如有侵权,请联系我们删除。

“Golang 编写测试用例(单元测试、压力测试等)最新教程,细到极致”的评论:

还没有评论