Golang 学习笔记② 单元测试
使用Golang的标准包testing可以创建Golang的单元测试。
验证环境的目录结构
golang
├main.go
└person
├person.go
└person_test.go
在VSCode中进行单元测试的方法
在想要测试的方法上打开上下文菜单,选择“生成函数单元测试”,即可生成测试代码。
testing会生成一个名为{待测试源文件名}_test.go的文件。

package main
import (
"fmt"
"./person"
)
func main() {
fmt.Println("start")
person.InitPerson()
}
package person
import "fmt"
// Person Recording Persons Score & rank.
type Person struct {
name string
english int
rank string
}
// InitPerson doing Initialize Person.
func InitPerson() {
Bob := Person{"Bob", 60, ""}
Bob.rank = Score(Bob)
fmt.Printf("Name:%v\n", Bob.name)
fmt.Printf("Score:%v\n", Bob.english)
fmt.Printf("rank:%v\n", Bob.rank)
}
// Score Return rank by score.
func Score(p Person) string {
if p.english > 80 {
return "A"
} else if p.english > 60 {
return "B"
} else {
return "C"
}
}
当对person.go中的Score方法进行测试时,将生成下面的测试代码。
package person
import (
"testing"
)
func TestScore(t *testing.T) {
type args struct {
p Person
}
tests := []struct {
name string
args args
want string
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Score(tt.args.p); got != tt.want {
t.Errorf("Score() = %v, want %v", got, tt.want)
}
})
}
}
不使用骨架,可以将测试值传递给生成的代码的结构体,并执行测试,
但是这次我们创建了以下的测试代码,而不使用骨架。
package person
import (
"testing"
)
func TestScore_1(t *testing.T) {
p := Person{"Bob", 60, ""}
actual := Score(p)
expected := "C"
if actual != expected {
t.Errorf("got %v want %v", actual, expected)
}
}
在VSCode上,当执行上面显示在方法顶部的运行测试功能时,可以按方法为单位执行测试。执行后,以下结果将在终端中输出。
Running tool: /usr/local/go/bin/go test -timeout 30s -run ^(TestScore_1)$
PASS
ok _/Users/username/golang/golang/person 0.010s
Success: Tests passed.
另外,在存储测试代码的目录中执行”go test .”,可以执行该目录中的所有测试。
我刚刚在代码中添加了两个新测试案例。
为了确认失败时的操作,我设置了TestScore_3作为一个NG案例。
package person
import (
"testing"
)
func TestScore_1(t *testing.T) {
p := Person{"Bob", 90, ""}
actual := Score(p)
expected := "A"
if actual != expected {
t.Errorf("got %v want %v", actual, expected)
}
}
func TestScore_2(t *testing.T) {
p := Person{"Bob", 80, ""}
actual := Score(p)
expected := "B"
if actual != expected {
t.Errorf("got %v want %v", actual, expected)
}
}
//NG case
func TestScore_3(t *testing.T) {
p := Person{"Bob", 60, ""}
actual := Score(p)
expected := "B"
if actual != expected {
t.Errorf("got %v want %v", actual, expected)
}
}
如果测试失败,则无法获得正常的结果,并将显示出引起失败的源代码部分和设定的错误信息在终端上。
一旦发生一个错误,后续的代码将不再执行。
$ go test .
--- FAIL: TestScore_3 (0.00s)
person_test.go:31: got C want B
FAIL
FAIL _/Users/username/golang/golang/person 0.006s
FAIL
获取报道
通过使用cover选项,可以获得代码覆盖率。
go test . -cover
ok _/Users/username/golang/golang/person 0.011s coverage: 50.0% of statements
另外,还可以将覆盖率作为HTML输出。
通过使用test的-coverprofile选项,将覆盖率文件输出到文件中,
然后再使用go tool cover将输出的文件转换为HTML文件。
$go test -coverprofile=cover.out ./
ok _/Users/username/golang/golang/person 0.007s coverage: 50.0% of statements
$ go tool cover -html=cover.out -o cover.html
将覆盖范围用HTML显示如下:
