Go 单元测试

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)
}
//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)
			}
		})
	}
}

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

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

帮助函数

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
}

在这里,我们故意创建了一个错误的测试用例,运行 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

可以看到,错误发生在第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)
		}
	})
}

运行 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

网络测试

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

func HelloHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello world"))
}
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")
	}
}
$ go test -run TestHelloHandler -v
=== RUN   TestHelloHandler
--- PASS: TestHelloHandler (0.00s)
PASS
ok      goProject       0.002s

测试覆盖率

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

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

你可能感兴趣的:(go学习,单元测试,golang,junit)