为什么需要单元测试

其实在很长一段时间,包括现在,我都很不喜欢写单元测试。因为维护单元测试的成本很高。只有接口做了一点变更,那么单元测试就必须做相同的变更,否则会导致测试不通过。

那么反过来,只要每次在提交代码都去运行一次单元测试。这样可以很快的检查到你对代码更改是否影响了正常的业务逻辑,当然很大一部分是可能是别人写的那部分代码。因为你不确定本次的修改是否会影响到别人的那部分。所以单元测试还是很有必要的。

单元测试最基本的应用

testunit

go test 最基本使用

go testgolang

go test -v

go test -v

新建一个项目用于示例

test
│  main.go
│  main_test.go
main.gomain_test.gogo文件名_test.go
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)
}
testingTestt *testing.Tt.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

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!")
}
cover66.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 filenameprofilego tool cover -html=test.cover -o coverage.htmlconverage.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/
Golangtesting
// 输出测试日志
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

更多学习内容,同步更新到公众号,期待与您一起交流