其实在很长一段时间,包括如今,我都很不喜欢写单元测试。由于维护单元测试的成本很高。只有接口作了一点变动,那么单元测试就必须作相同的变动,不然会致使测试不经过。html
那么反过来,只要每次在提交代码都去运行一次单元测试。这样能够很快的检查到你对代码更改是否影响了正常的业务逻辑,固然很大一部分是多是别人写的那部分代码。由于你不肯定本次的修改是否会影响到别人的那部分。因此单元测试仍是颇有必要的。git
go语言中单元测试是开箱即用的,官方提供了test
包。不用像PHP中须要单独配置unit
。github
go test
命令是golang
单元测试的最基本使用golang
go test -v
是咱们比较经常使用的一个测试命令,用于执行测试,并打印额外的输出。
新建一个项目用于示例微信
test │ main.go │ main_test.go
能够看到我在main.go
的同级目录建立了一个main_test.go
。go
语言中,单元测试的代码必须跟须要测试的代码在同一个包里面。且命名必须遵循上面的那种结构规范,即:文件名_test.go
app
我在main.go
中建立两个函数来分别获得字符串相加的结果。函数
func JoinStrUseSprint(a,b string) string { return fmt.Sprintf("%s%s",a,b) } func JoinStrUseNor(a,b string) string { return a+b }
main_test.go
中的测试代码工具
import "testing" func TestJoinStrUseNor(t *testing.T) { c := JoinStrUseNor("aaa","bbb") t.Log(c) } func TestJoinStrUseSprint(t *testing.T) { c := JoinStrUseSprint("aaa","bbb") t.Log(c) }
测试代码中使用了 testing
包。并且每一个测试函数必须是以Test
开头,有且只有一个参数t *testing.T
.t.Log()
函数为输出一段Log
日志 这样一个简单的单元测试就完成了。单元测试
这个时候咱们运行go test
,结果以下。学习
test>go test PASS ok test 0.360s
能够看到测试经过了。可是发现并无咱们指望的日志输出。若是咱们要获得输出的结果,咱们须要一个额外的参数,具体命令以下:
test>go test -v === RUN TestJoinStrUseNor --- PASS: TestJoinStrUseNor (0.00s) main_test.go:7: aaabbb === RUN TestJoinStrUseSprint --- PASS: TestJoinStrUseSprint (0.00s) main_test.go:12: aaabbb PASS ok test 0.480s
这个时候就能够看到很详细的测试流程与输出的测试的log
。
不少时间咱们须要看单元测试的覆盖率,这个时候咱们就须要
go test -cover
了。
咱们一样使用上面的代码。
test>go test -cover PASS coverage: 100.0% of statements ok test 0.440s
能够看到单元代码覆盖率是100%
。这个是咱们在main
文件里面在增长一个函数。
func JoinStrUseSprint(a,b string) string { return fmt.Sprintf("%s%s",a,b) } func JoinStrUseNor(a,b string) string { return a+b } func Run() { fmt.Println("I'm run,and I'm happy!") }
而后再执行cover
,获得了覆盖率为66.7
。
test>go test -cover PASS coverage: 66.7% of statements ok test 0.398s
固然-v -cover
是能够同事使用的。
test>go test -cover -v === RUN TestJoinStrUseNor --- PASS: TestJoinStrUseNor (0.00s) main_test.go:7: aaabbb === RUN TestJoinStrUseSprint --- PASS: TestJoinStrUseSprint (0.00s) main_test.go:12: aaabbb PASS coverage: 66.7% of statements ok test 0.429s
不少时候咱们须要将单元测试覆盖率写到一个文件中,这时候咱们再-cover
中增长一些额外的参数
>go test -coverprofile test.cover >go tool cover -html=test.cover -o coverage.html
-coverprofile filename
将覆盖率的profile
写入指定文件中。go tool cover -html=test.cover -o coverage.html
将覆盖率的文件写入可视化的html文件中打开converage.html
以下图:
其实这里能够借用一个很好的第三方包。
go get github.com/smartystreets/goconvey
安装完成,直接再项目目录下执行
test>goconvey 2020/05/16 21:46:43 goconvey.go:61: Initial configuration: [host: 127.0.0.1] [port: 8080] [poll: 250ms] [cover: true] 2020/05/16 21:46:43 tester.go:19: Now configured to test 10 packages concurrently. 2020/05/16 21:46:43 goconvey.go:178: Serving HTTP at: http://127.0.0.1:8080 2020/05/16 21:46:43 integration.go:122: File system state modified, publishing current folders... 0 3179270049 2020/05/16 21:46:43 goconvey.go:118: Received request from watcher to execute tests... 2020/05/16 21:46:43 goconvey.go:105: Launching browser on 127.0.0.1:8080 2020/05/16 21:46:43 goconvey.go:111: exec: "start": executable file not found in %PATH% 2020/05/16 21:46:43 goconvey.go:113: 2020/05/16 21:46:44 executor.go:69: Executor status: 'executing' 2020/05/16 21:46:44 coordinator.go:46: Executing concurrent tests: test 2020/05/16 21:46:45 parser.go:24: [passed]: test
按照提示打开http://127.0.0.1:8080/
就会获得一个很炫酷的覆盖率界面
Golang
单元测试的基础今天就暂时到这里面,下面几个testing
包的经常使用断言方法.
// 输出测试日志 t.Logf() t.Logf() // 标记错误,但仍然执行后面的语句 t.Fail() // 获取是否当前用例是执行错误的 t.Failed() // 错误输出,等于 t.Logf 再执行 t.Fail() t.Errorf("%s", "run ErrorF") // 标记函数错误,并中断后面的执行 t.FailNow() // 致命错误输出,等同于调用了 t.Logf 而后调用 t.FailNow() t.Fatalf("%s", "run Fatelf")
下一篇咱们会写到 golang
中的一些基准测试,以及一些测试的工具。
更多学习内容,同步更新到公众号,期待与您一块儿交流