Jinyun's Notes 🚀

没什么天赋,爱好也不多,但愿坚持做些喜欢的事情

0%

Go 其它测试

Go 的 testing 包除了测试,还提供了运行并验证示例的功能。一方面是文档的效果,是关于某个功能的使用例子;另一方面,可以被当做测试运行。

示例测试

示例测试函数格式

Go 语言通过大量的命名约定来简化工具的复杂度,规范代码的风格。对示例函数的命名有如下约定:

  • 包级别的示例函数,直接命名为:func Example() { ... }
  • 函数 F 的示例,命名为:func ExampleF() { ... }
  • 类型 T 的示例,命名为:func ExampleT() { ... }
  • 类型 T 上的方法 M 的示例,命名为:func ExampleT_M() { ... }

有时,我们想要给 包/类型/函数/方法 提供多个示例,可以通过在示例函数名称后附加一个不同的后缀来实现,但这种后缀必须以小写字母开头,如:

1
2
3
4
func Example_suffix()    { ... }
func ExampleF_suffix() { ... }
func ExampleT_suffix() { ... }
func ExampleT_M_suffix() { ... }

示例测试实例

示例一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package hello

import (
"fmt"
"strings"
)

func ExampleToUpper() {
fmt.Println(strings.ToUpper("foo"))
// Output: FOO
}

func ExampleToUpperFail() {
fmt.Println(strings.ToUpper("bar"))
// Output: Bar
}
1
2
3
4
5
6
7
8
9
10
11
12
$ go test -v -timeout 30s -run '^(ExampleToUpper|ExampleToUpperFail)$' example.com/hello

=== RUN ExampleToUpper
--- PASS: ExampleToUpper (0.00s)
=== RUN ExampleToUpperFail
--- FAIL: ExampleToUpperFail (0.00s)
got:
BAR
want:
Bar
FAIL
FAIL example.com/hello 0.008s

示例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package hello

import (
"fmt"
"sort"
)

type Person struct {
Name string
Age int
}

func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

// ByAge implements sort.Interface for []Person based on the Age field.
type SortByAge []Person

func (a SortByAge) Len() int { return len(a) }
func (a SortByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a SortByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }

func Example() {
people := []Person{
{"Jack", 31},
{"John", 42},
{"Acme", 17},
{"Pony", 26},
{"Wise", 33},
}

fmt.Println(people)
sort.Sort(SortByAge(people))
fmt.Println(people)

// Output:
// [Jack: 31 John: 42 Acme: 17 Pony: 26 Wise: 33]
// [Acme: 17 Pony: 26 Jack: 31 Wise: 33 John: 42]
}
1
2
3
4
5
6
$ go test -v -timeout 30s example.com/hello

=== RUN Example
--- PASS: Example (0.00s)
PASS
ok example.com/hello 0.007s

实例三

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package hello

import (
"go/ast"
"go/parser"
"log"
)

func ExampleAST() {
expr, err := parser.ParseExpr("9 / (2 + 1)")
if err != nil {
log.Fatal(err)
}
ast.Print(nil, expr)
// Output: 0 *ast.BinaryExpr {
// 1 . X: *ast.BasicLit {
// 2 . . ValuePos: 1
// 3 . . Kind: INT
// 4 . . Value: "9"
// 5 . }
// 6 . OpPos: 3
// 7 . Op: /
// 8 . Y: *ast.ParenExpr {
// 9 . . Lparen: 5
// 10 . . X: *ast.BinaryExpr {
// 11 . . . X: *ast.BasicLit {
// 12 . . . . ValuePos: 6
// 13 . . . . Kind: INT
// 14 . . . . Value: "2"
// 15 . . . }
// 16 . . . OpPos: 8
// 17 . . . Op: +
// 18 . . . Y: *ast.BasicLit {
// 19 . . . . ValuePos: 10
// 20 . . . . Kind: INT
// 21 . . . . Value: "1"
// 22 . . . }
// 23 . . }
// 24 . . Rparen: 11
// 25 . }
// 26 }
}
1
2
3
4
5
6
$ go test -v -timeout 30s -run '^ExampleAST$' example.com/hello

=== RUN ExampleAST
--- PASS: ExampleAST (0.00s)
PASS
ok example.com/hello (cached)

主函数测试

注意:在 TestMain 函数的最后,应该使用 m.Run 的返回值作为参数去调用 os.Exit

在写测试时,有时需要在测试之前或之后进行额外的设置(setup)或拆卸(teardown);有时,测试还需要控制在主线程上运行的代码。为了支持这些需求,testing 包提供了 TestMain 函数(附上 官方 TestMain 使用姿势):

1
func TestMain(m *testing.M)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package hello

import (
"log"
"os"
"testing"
)

func TestMain(m *testing.M) {
log.Println("Do stuff BEFORE the tests!")
exit := m.Run()
log.Println("Do stuff AFTER the tests!")

os.Exit(exit)
}

func TestA(t *testing.T) {
log.Println("TestA running")
}

func TestB(t *testing.T) {
log.Println("TestB running")
}
1
2
3
4
5
6
7
8
9
10
11
12
$ go test -v -timeout 30s -run '^(TestMain|TestA|TestB)$' example.com/hello

2021/07/22 20:07:25 Do stuff BEFORE the tests!
=== RUN TestA
2021/07/22 20:07:25 TestA running
--- PASS: TestA (0.00s)
=== RUN TestB
2021/07/22 20:07:25 TestB running
--- PASS: TestB (0.00s)
PASS
2021/07/22 20:07:25 Do stuff AFTER the tests!
ok example.com/hello (cached)
本笔记是笔者在学习和工作中的一些整理,如对您有用,请鼓励我继续写作