• Go 单元测试



    单元测试就是在终端使用go test进行我们自定义的测试,代码编写要求如下:

    Go 语言推荐测试文件和源代码文件放在一块,测试文件以 _test.go 结尾,例如我们需要测试写在mytry.go里的Add函数,则测试文件名为mytry_test.go

    测试用的函数名为需要测试的函数前加Test,如要测试Add,则测试用函数名为TestAdd

    有多个待测试函数时,可以用-run来选择运行其中的一个用例
    go test -run TestAdd

    -v可以显示每个用例的测试结果

    多个子测试

    //mytry.go
    package main
    
    func Add(a int, b int) int {
        return a + b
    }
    
    func main(){
    	ret:=Add(1,2)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    //mytry_test.go
    package main
    
    import "testing"
    
    func TestAdd(t *testing.T){
    	cases:=[]struct{
    		Name string
    		A,B,Want int
    	}{
    		{"pos",2,3,5},
    		{"neg",2,-4,-2},
    		{"zero",2,-2,0},
    	}
    
    	for _,c:=range cases{
    		t.Run(c.Name,func(t *testing.T){
    			if Get:=Add(c.A,c.B);Get!=c.Want{
    				t.Errorf("Name:%s,Want:%d,Get:%d",c.Name,c.Want,Get)
    			}
    		})
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    go test -run TestAdd -v

    === RUN   TestAdd
    === RUN   TestAdd/pos
    === RUN   TestAdd/neg
    === RUN   TestAdd/zero
    --- PASS: TestAdd (0.00s)
        --- PASS: TestAdd/pos (0.00s)
        --- PASS: TestAdd/neg (0.00s)
        --- PASS: TestAdd/zero (0.00s)
    PASS
    ok      goProject       0.002s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    go test -run TestAdd/zero -v

    === RUN   TestAdd
    === RUN   TestAdd/zero
    --- PASS: TestAdd (0.00s)
        --- PASS: TestAdd/zero (0.00s)
    PASS
    ok      goProject       0.002s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    帮助函数

    t.Helper(),用于标注该函数是帮助函数,报错时将输出帮助函数调用者的信息,而不是帮助函数的内部信息。

    // calc_test.go
    package main
    
    import "testing"
    
    type calcCase struct{ A, B, Expected int }
    
    func createMulTestCase(t *testing.T, c *calcCase) {
    	// t.Helper()
    	if ans := Mul(c.A, c.B); ans != c.Expected {
    		t.Fatalf("%d * %d expected %d, but %d got",
    			c.A, c.B, c.Expected, ans)
    	}
    
    }
    
    func TestMul(t *testing.T) {
    	createMulTestCase(t, &calcCase{2, 3, 6})
    	createMulTestCase(t, &calcCase{2, -3, -6})
    	createMulTestCase(t, &calcCase{2, 0, 1}) // wrong case
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里,我们故意创建了一个错误的测试用例,运行 go test,用例失败,会报告错误发生的文件和行号信息:

    $ go test
    --- FAIL: TestMul (0.00s)
        calc_test.go:11: 2 * 0 expected 1, but 0 got
    FAIL
    exit status 1
    FAIL    example 0.007s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以看到,错误发生在第11行,也就是帮助函数 createMulTestCase 内部。18, 19, 20行都调用了该方法,我们第一时间并不能够确定是哪一行发生了错误。有些帮助函数还可能在不同的函数中被调用,报错信息都在同一处,不方便问题定位。
    如果我们标注帮助函数

    func createMulTestCase(c *calcCase, t *testing.T) {
        t.Helper()
    	t.Run(c.Name, func(t *testing.T) {
    		if ans := Mul(c.A, c.B); ans != c.Expected {
    			t.Fatalf("%d * %d expected %d, but %d got",
    				c.A, c.B, c.Expected, ans)
    		}
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行 go test,报错信息如下,可以非常清晰地知道,错误发生在第 20 行。

    $ go test
    --- FAIL: TestMul (0.00s)
        calc_test.go:20: 2 * 0 expected 1, but 0 got
    FAIL
    exit status 1
    FAIL    example 0.006s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    网络测试

    假设需要测试某个 API 接口的 Handler 能够正常工作,例如 HelloHandler

    func HelloHandler(w http.ResponseWriter, r *http.Request) {
    	w.Write([]byte("hello world"))
    }
    
    • 1
    • 2
    • 3
    package main
    
    import (
    	"fmt"
    	"net/http"
    	"net/http/httptest"
    	"testing"
    )
    
    func TestHelloHandler(t *testing.T) {
    	req, err := http.NewRequest("GET", "/", nil)	//这里的url好像可以随便写
    	if err != nil {
    		fmt.Println(err)
    	}
    	ret := httptest.NewRecorder()
    	HelloHandler(ret, req)
    	if ret.Body.String() != "hello world" {
    		fmt.Println("handler erro")
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    $ go test -run TestHelloHandler -v
    === RUN   TestHelloHandler
    --- PASS: TestHelloHandler (0.00s)
    PASS
    ok      goProject       0.002s
    
    • 1
    • 2
    • 3
    • 4
    • 5

    测试覆盖率

    go test -v -coverprofile=c.out
    
    • 1
    go tool cover -html=c.out
    
    • 1

    会在浏览器生成一个包含测试函数的页面,绿色的就是覆盖到了的,红色是没覆盖到的

  • 相关阅读:
    关于df[‘某一列名’][序号]
    西安有哪些比较好的设计院?西安名企设计院介绍!
    浅谈mysql扩展之读写分离、垂直分区、水平分区
    软件测试面试题及答案 这个可以免费白嫖的题库不要错过了
    uniapp项目实践总结(二十一)日常开发方法汇总
    聚苯乙烯/聚4-乙烯基吡啶功能微球/CF3-PPFPA-PS聚苯胺/聚苯乙烯微球的制备
    如何成就更高远控帧率和流畅度?向日葵SADDC算法浅析
    Javascript前端解析操作返回的各种类型的数据
    用遗传算法求解多旅行推销员问题的新方法
    流媒体学习之路(WebRTC)——音频NackTracker优化思路(8)
  • 原文地址:https://blog.csdn.net/qq_34688283/article/details/125993484