go 测试

35 阅读2分钟

date 2022-09-21

1. 单元测试

单元测试是指对软件中的最小可测试单元进行检查和验证,比如对一个函数的测试。

测试文件可以跟源文件在同一个包中,但通常的做法是创建一个专门的包进行测试

  1. 新建文件夹 gotest,并进入 gotest 文件夹
  2. 执行go mod init gotest命令,初始化 module
  3. 新建源代码文件<文件名>.go,本例中为 unit.go,包名为 gotest
  4. 新建源代码文件对应的测试文件<文件名_test>.go,本例中为 unit_test.go,包名为gotest_test
  5. 执行单元测试,在 gotest 文件夹,执行 go test 命令

unit.go

package gotest

func Add(a, b int) int {
	return a + b
}

unit_test.go

package gotest_test

import (
	"gotest"
	"testing"
)

func TestAdd(t *testing.T) {
	var a = 1
	var b = 2
	var expected = 3

	actual := gotest.Add(a, b)
	if actual != expected {
		t.Errorf("Add(%d, %d) = %d; expected: %d", a, b, actual, expected)
	}
}
(base) chen@chen:~/codespace/go_zero_from/gotest$ go test
PASS
ok  	gotest	0.001s

注意:

  1. 测试文件必须以_test.go结尾
  2. 测试函数必须以TextXxx开始
  3. 在命令行下使用go test即可启动测试

2. 性能测试(基准测试)

性能测试也称基准测试,可以测试一段程序,可以得到时间消耗,内存使用情况的报告。

测试文件可以跟源文件在同一个包中,但通常的做法是创建一个专门的包进行测试

  1. 新建文件夹 gobenchmark,并进入 gobenchmark 文件夹
  2. 执行go mod init gobenchmark命令,初始化 module
  3. 新建源代码文件<文件名>.go,本例中为 benchmark.go,包名为 gobenchmark
  4. 新建源代码文件对应的测试文件<文件名_test>.go,本例中为 gobenchmark_test.go,包名为benchmark_test
  5. 执行单元测试,在 gobenchmark 文件夹,执行 go test -bench=. 命令

benchmark.go

package gobenchmark

const COUNT = 100000

func MakeSliceWithoutPreAlloc() []int {
	var newSlice []int

	for i := 0; i < COUNT; i++ {
		newSlice = append(newSlice, i)
	}

	return newSlice
}

func MakeSliceWithPreAlloc() []int {
	var newSlice []int

	newSlice = make([]int, COUNT)
	for i := 0; i < COUNT; i++ {
		newSlice = append(newSlice, i)
	}

	return newSlice
}

benchmark_test.go

package gobenchmark_test

import (
	"gobenchmark"
	"testing"
)

func BenchmarkMakeSliceWithoutPreAlloc(b *testing.B) {
	for i := 0; i < b.N; i++ {
		gobenchmark.MakeSliceWithoutPreAlloc()
	}
}

func BenchmarkMakeSliceWithPreAlloc(b *testing.B) {
	for i := 0; i < b.N; i++ {
		gobenchmark.MakeSliceWithPreAlloc()
	}
}
(base) chen@chen:~/codespace/go_zero_from/gobenchmark$ go test -bench=.
goos: linux
goarch: amd64
pkg: gobenchmark
cpu: Intel(R) Core(TM) i5-9400 CPU @ 2.90GHz
BenchmarkMakeSliceWithoutPreAlloc-6   	    1998	    907071 ns/op
BenchmarkMakeSliceWithPreAlloc-6      	     388	   3039695 ns/op
PASS
ok  	gobenchmark	3.368s

注意:

  1. 测试文件必须以_test.go结尾
  2. 测试函数必须以BenchmarkXxx开始
  3. 在命令行下使用go test -bench=.即可启动测试

3. 示例测试

用于展示某个包或某个方法的用法

测试文件可以跟源文件在同一个包中,但通常的做法是创建一个专门的包进行测试

  1. 新建文件夹 goexample,并进入 goexample 文件夹
  2. 执行go mod init goexample命令,初始化 module
  3. 新建源代码文件<文件名>.go,本例中为 example.go,包名为 goexample
  4. 新建源代码文件对应的测试文件<文件名_test>.go,本例中为 example_test.go,包名为goexample_test
  5. 执行单元测试,在 goexample 文件夹,执行 go test example_test.go 命令

example.go

package goexample

import "fmt"

func SayHello() {
	fmt.Println("Hello World")
}

func SayGoodbye() {
	fmt.Println("Hello,")
	fmt.Println("goodbye")
}

func PrintNames() {
	students := make(map[int]string, 4)
	students[1] = "Jim"
	students[2] = "Bob"
	students[3] = "Tom"
	students[4] = "sue"
	for _, value := range students {
		fmt.Println(value)
	}
}

example_test.go

package goexample_test

import "goexample"

func ExampleSayHello() {
	goexample.SayHello()
	//OutPut: Hello World
}

func ExampleSayGoodbye() {
	goexample.SayGoodbye()
	//OutPut:
	//Hello,
	//goodbye
}

func ExamplePrintNames() {
	goexample.PrintNames()
	//Unorderd output:
	//Jim
	//Bob
	//Tom
	//sue
}
(base) chen@chen:~/codespace/go_zero_from/test/goexample$ go test example_test.go 
ok  	command-line-arguments	0.001s

注意:

  1. 示例测试函数名需要以Example开头
  2. 检测单行输出格式为// Output: <期望字符串>
  3. 检测多行输出格式为// Output: <期望字符串> \n <期望字符串>,每个字符串占一行
  4. 测试无序输出格式为: //Unorderd output: <期望字符串> \n <期望字符串>,每个字符串占一行
  5. 测试字符串时会自动忽略字符串前后的空白字符
  6. 如果测试函数没有Output标识,测试该函数不会被执行
  7. 执行测试可以使用go test,此刻该目录下的其他测试文件也一并会执行
  8. 执行测试可以使用go test <xxx_test.go>,此刻仅执行特定文件中的测试函数