Go笔记-测试

测试用例

  • 文件名必须是_test.go结尾的,这样在执行go test的时候才会执行到相应的代码
  • 你必须import testing这个包
  • 全部的测试用例函数必须是Test开头
  • 测试用例会按照源代码中写的顺序依次执行
  • 测试函数TestXxx()的参数是testing.T,咱们可使用该类型来记录错误或者是测试状态
  • 测试格式:func TestXxx (t *testing.T),Xxx部分能够为任意的字母数字的组合,可是首字母不能是小写字母[a-z],例如Testintdiv是错误的函数名。
  • 函数中经过调用testing.T的Error, Errorf, FailNow, Fatal, FatalIf方法,说明测试不经过,调用Log方法用来记录测试的信息。
go test -v -run=函数名正则 包路径
package gotest

import (
    "testing"
)

func Test_Division_1(t *testing.T) {
    if i, e := Division(6, 2); i != 3 || e != nil { //try a unit test on function
        t.Error("除法函数测试没经过") // 若是不是如预期的那么就报错
    } else {
        t.Log("第一个测试经过了") //记录一些你指望记录的信息
    }
}

func Test_Division_2(t *testing.T) {
    t.Error("就是不经过")
}

咱们在项目目录下面执行go test,就会显示以下信息:html

--- FAIL: Test_Division_2 (0.00 seconds)
    gotest_test.go:16: 就是不经过
FAIL
exit status 1
FAIL    gotest  0.013s

从这个结果显示测试没有经过,由于在第二个测试函数中咱们写死了测试不经过的代码t.Error,那么咱们的第一个函数执行的状况怎么样呢?默认状况下执行go test是不会显示测试经过的信息的,咱们须要带上参数go test -v,这样就会显示以下信息:node

=== RUN Test_Division_1
--- PASS: Test_Division_1 (0.00 seconds)
    gotest_test.go:11: 第一个测试经过了
=== RUN Test_Division_2
--- FAIL: Test_Division_2 (0.00 seconds)
    gotest_test.go:16: 就是不经过
FAIL
exit status 1
FAIL    gotest  0.012s

代码覆盖率

go test -cover -v

经过在每一个代码块中插入布尔类型的变量,统计代码是否被执行。web

可视化数据库

go test -coverprofile=c.out
go tool cover -html=c.out

使用 -covermode=count 在每行代码中插入计数器而不是布尔变量。bash

压力测试

压力测试用来检测函数(方法)的性能,和编写单元功能测试的方法相似,此处再也不赘述,但须要注意如下几点:并发

  • 压力测试用例必须遵循以下格式,其中XXX能够是任意字母数字的组合,可是首字母不能是小写字母函数

    func BenchmarkXXX(b *testing.B) { ... }oop

  • go test不会默认执行压力测试的函数,若是要执行压力测试须要带上参数-test.bench,语法:-test.bench="test_name_regex",例如go test -test.bench=".*"表示测试所有的压力测试函数性能

  • -bench也能够, bench可使用|(-bench='A|bcd|EFG', -bench=Benchmark(A|B))单元测试

  • 在压力测试用例中,请记得在循环体内使用testing.B.N,以使测试能够正常的运行

  • 文件名也必须以_test.go结尾

package gotest

import (
    "testing"
)

func Benchmark_Division(b *testing.B) {
    for i := 0; i < b.N; i++ { //use b.N for looping 
        Division(4, 5)
    }
}

func Benchmark_TimeConsumingFunction(b *testing.B) {
    b.StopTimer() //调用该函数中止压力测试的时间计数

    //作一些初始化的工做,例如读取文件数据,数据库链接之类的,
    //这样这些时间不影响咱们测试函数自己的性能

    b.StartTimer() //从新开始时间
    for i := 0; i < b.N; i++ {
        Division(4, 5)
    }
}

咱们执行命令go test -file webbench_test.go -test.bench=".*",能够看到以下结果:

PASS
Benchmark_Division  500000000            7.76 ns/op
Benchmark_TimeConsumingFunction 500000000            7.80 ns/op
ok      gotest  9.364s

上面的结果显示咱们没有执行任何TestXXX的单元测试函数,显示的结果只执行了压力测试函数,第一条显示了Benchmark_Division执行了500000000次,每次的执行平均时间是7.76纳秒,第二条显示了Benchmark_TimeConsumingFunction执行了500000000,每次的平均执行时间是7.80纳秒。最后一条显示总共的执行时间。

go test -v -run=XXX -bench=函数名正则 包路径

记录cpu占用

go test -v -run=XXX -bench=函数名正则 -cpuprofile=cpu.out sms

会在当前目录下生成一个以".test"结尾的文件和一个cpu.out,查看的话使用:

go tool pprof ./XX.test cpu.out

文本输出:

go tool pprof -text -nodecount=10 ./XX.test cpu.log

-text 标志参数用于指定输出格式, 在这里每行是一个函数, 根据使用CPU的时间来排 序

-nodecount=10 标志参数限制了只输出前10行的结果

记录内存分配

添加 -benchmem

并发测试

b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			// some code
		}
	})

例子用例

  • 文件名也是以 _test 结尾
  • 使用fmt包输出,使用注释 // Output: 来验证输出是否正确。
  • Example[FunctionName] 针对FunctionName的例子,会显示在FunctionName的下,若是没有FunctionName则会显示在Overview下。
func ExampleInts() {
	s := []int{5, 2, 6, 3, 1, 4} // unsorted
	sort.Ints(s)
	fmt.Println(s)
	// Output: [1 2 3 4 5 6]
}

测试脚本

除vendor外的测试

IGNORE_PKGS="(vendor)"
TEST_PKGS=`find . -name \*_test.go | while read a; do dirname $a; done | sort | uniq | egrep -v "$IGNORE_PKGS" | sed "s|\./||g"`

说明:

find . -name \*_test.go 找到全部的测试文件。

dirname 获取全路径中的目录部分,好比 a/b/c.txt 获取的是 a/b

sed "s|\./||g 去掉 ./

最后的结果就是列举出本身写的 _test.go 文件。

相关文章
相关标签/搜索