Python 程序员的 Golang 学习指南(V): 测试篇
Golang
  • 调试篇
  • 打包篇

这篇文章我们介绍下 Go 语言中如何进行测试。

单元测试

  • 功能测试
testinggo test

编写测试代码需遵循以下原则

_test.gogo testtestingTestTestXxx()testing.Tfunc TestXxx (t *testing.T)XxxTestintdivtesting.TErrorErrorfFailNowFatalFatalIfLog
stringutil.go
  1. // Package stringutil contains utility functions for working with strings.
  2. package stringutil
  3. // Reverse returns its argument string reversed rune-wise left to right.
  4. func Reverse(s string) string {
  5. r := []rune(s)
  6. for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
  7. r[i], r[j] = r[j], r[i]
  8. }
  9. return string(r)
  10. }

那我们的测试用例可以写成下面这样:

  1. package stringutil
  2. import "testing"
  3. func TestReverse(t *testing.T) {
  4. const in, want = "Hello, world", "dlrow ,olleH"
  5. got := Reverse(in)
  6. if got != want {
  7. t.Errorf("Reverse(%q) == %q, want %q", in, got, want)
  8. }
  9. }
go test -v
  1. === RUN TestReverse
  2. --- PASS: TestReverse (0.00s)
  3. PASS
  4. ok github.com/startover/testing 0.001s
  • 基准测试

基准测试与功能测试类似,不过有以下几点需要注意:

func BenchmarkXXX(b *testing.B) { ... }go test-test.bench-test.bench="test_name_regex"go test -test.bench=".*"testing.B.N_test.go

代码示例如下:

  1. package stringutil
  2. import "testing"
  3. func BenchmarkReverse(b *testing.B) {
  4. const in = "Hello, world"
  5. for n := 0; n < b.N; n++ {
  6. Reverse(in)
  7. }
  8. }
go test -v -test.bench=".*"
  1. PASS
  2. BenchmarkReverse-4 5000000 260 ns/op
  3. ok github.com/startover/testing 1.579s
  • 表驱动测试

编写测试代码时,一个较好的办法是把测试的输入数据和期望的结果写在一起组成一个数据表:表中的每条记录都是一个含有输入和期望值的完整测试用例,有时还可以结合像测试名字这样的额外信息来让测试输出更多的信息。这就是表驱动测试

Go 语言的 struct 字面值语法让我们可以轻松写出表驱动测试,代码示例如下:

  1. package stringutil
  2. import "testing"
  3. func TestTableReverse(t *testing.T) {
  4. for _, c := range []struct {
  5. in, want string
  6. }{
  7. {"Hello, world", "dlrow ,olleH"},
  8. {"Hello, 世界", "界世 ,olleH"},
  9. {"", ""},
  10. } {
  11. got := Reverse(c.in)
  12. if got != c.want {
  13. t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
  14. }
  15. }
  16. }
  • 测试覆盖率
go test -v -cover
  1. $ go test -v -cover
  2. === RUN TestReverse
  3. --- PASS: TestReverse (0.00s)
  4. === RUN TestTableReverse
  5. --- PASS: TestTableReverse (0.00s)
  6. PASS
  7. coverage: 100.0% of statements
  8. ok github.com/startover/testing 0.004s
go testcover
  1. $ go test -coverprofile=cover.out
  2. $ go tool cover -func=cover.out
  3. github.com/startover/testing/stringutil.go:5: Reverse 100.0%
  4. total: (statements) 100.0%

BDD 测试

Go 语言比较主流的 BDD 测试框架主要有:GoConvey 和 Ginkgo。下面让我们感受下 BDD 风格的测试代码:

  1. package stringutil
  2. import (
  3. "testing"
  4. . "github.com/smartystreets/goconvey/convey"
  5. )
  6. func TestSpec(t *testing.T) {
  7. // Only pass t into top-level Convey calls
  8. Convey("Given some ASCII and UTF8 strings", t, func() {
  9. const in, want = "Hello, world", "dlrow ,olleH"
  10. Convey("The value should be equal the reversed one", func() {
  11. got := Reverse(in)
  12. So(got, ShouldEqual, want)
  13. })
  14. })
  15. }
  1. package stringutil
  2. import (
  3. . "github.com/onsi/ginkgo"
  4. . "github.com/onsi/gomega"
  5. )
  6. var _ = Describe("StringutilTest", func() {
  7. var in, want string
  8. BeforeEach(func() {
  9. const in, want = "Hello, world", "dlrow ,olleH"
  10. })
  11. Describe("With ASCII and UTF8 strings defined", func() {
  12. Context("Reverse the give strings", func() {
  13. It("should be reversed", func() {
  14. got := Reverse(in)
  15. Expect(got).To(Equal(want))
  16. })
  17. })
  18. })
  19. })
ginkgo -rgo test

相关链接:
https://talks.golang.org/2014/testing.slide#1
https://nathany.com/go-testing-toolbox/
http://codethoughts.info/go/2015/04/05/how-to-test-go-code/
https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/11.3.md