zoukankan      html  css  js  c++  java
  • go test 上篇

    前言

    Go语言本身集成了轻量级的测试框架,由go test命令和testing包组成。包含单元测试和压力测试,是保证我们编写健壮Golang程序的有效工具。

    演示环境

    $ uname -a
    Darwin 18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64
    $ go version
    go version go1.12.4 darwin/amd64

    示例

    老规矩,我会用一个简单的示例演示go test的用法,让大家有一个直观的感受。

    $ ls
    my.go my_test.go
    $ go test -v
    === RUN   TestAbs
    --- PASS: TestAbs (0.00s)
    PASS
    ok      mytest    0.006s

    my.go文件内容:

    package mytest
    
    func Abs(a int) int {
        if a < 0 {
            return -1*a
        }
        return a
    }

    my_test.go文件的内容:

    package mytest
    
    import "testing"
    
    func TestAbs(t *testing.T) {
        result := Abs(-1)
        if result != 1 {
            t.Errorf("Abs(-1) = %d; want 1", result)
        }
    }

    可以看出,测试文件是以_test.go结尾的文件,包含函数名TestXXX的文件签名func (t *testing.T)。测试框架会按函数定义的顺序依次执行Test开头的函数。如果测试函数调用错误函数,比如t.Error,t.Fail,那么测试就会认为是失败的。但是不会强制退出,测试程序还是会接着往下运行,除非调用t.Fatal,就会打印错误信息,并且强制退出。go test会自动编译运行_test.go结尾的文件,go build不会编译_test.go结尾的文件,所以不用担心test文件和正式文件定义为同一个包导致包大小增大。

    详细用法

    go test执行时会编译_test结尾的文件,执行文件中以Test,Benchmark,Example 开头的测试函数。建议_test.go文件和源文件声明为同一个包。单元测试函数TestXXX的参数是testing.T,BenchmarkXXX的参数是testing.B,函数内以b.N作为循环次数,其中N会动态变化。可以通过testing.T的Error,Errorf,Fail,Fatal,Fatalf 来说明测试不通过。

     

    表格驱动测试

    上述的示例单元测试用了-1这个测试用例来演示测试用法,但是在实际生产中我们编写一个测试函数肯定会有多种测试用例,各种边界条件,那这种情况应该怎么办呢?难道要每个测试用例拷贝一份上述的测试函数吗,显然是不合适的。这就介绍接下来的表格驱动测试(table driven test):

    package mytest
    
    import "testing"
    
    func TestAbs(t *testing.T) {
        var testcases = []struct {
            in int
            out int
        }{
            {-1, 1},
            {0, 0},
            {2, 2},
            {123, 123},
            {-30, -30},
        }
        for _, tc := range testcases {
            result := Abs(tc.in)
            if result != tc.out {
                t.Fatalf("Abs(%d) = %d; want %d", tc.in, result, tc.out)
            }
        }
    
    }

    表格的每一项是一个完整的测试用例,包含输入信息和期望的输出结果,有时候还包含测试用例名称等额外信息。这样我们就可以在表格里面编写各种测试用例场景,包括常规场景,边界场景,和一些异常场景。运行结果为:

    $ go test -v
    === RUN   TestAbs
    --- FAIL: TestAbs (0.00s)
        my_test.go:19: Abs(-30) = 30; want -30
    FAIL
    exit status 1
    FAIL    mytest    0.005s

    性能测试

    性能测试函数以是Benchmark开头,格式为:

    func Benchmark(b *testing.B)

    go test 默认是不会运行_test.go文件中的Benchmark函数,需要通过-bench选项开启。演示代码:

    package mytest
    
    import "testing"
    
    func BenchmarkAbs(b *testing.B) {
        for i := 0; i < b.N; i++ {
            result := Abs(i)
            if result != i {
                b.Errorf("benchmark faild, abs(%d) result %d, except %d", i, result, i)
            }
        }
    }

    运行结果:

    $ go test -bench=".*"
    goos: darwin
    goarch: amd64
    pkg: mytest
    BenchmarkAbs-12        2000000000             0.26 ns/op
    PASS
    ok      mytest    0.553s

    -bench后面跟的是正则表达式,我们可以指定需要匹配运行的benchmark函数,示例中的.*表示运行所有的benchmark函数。

    上述结果显示总共运行了0.553s,一共运行了2000000000次,平均每次运行的时间是0.26纳秒。

    总结

    文章介绍了Go语言自带的go test测试框架的单元测试和性能测试方法。下篇将会讲解gomock模拟实际的生产接口。

    参考

    https://golang.org/pkg/testing/

    https://github.com/golang/go/wiki/TableDrivenTests

    https://golang.org/doc/code.html#Testing

  • 相关阅读:
    java实例:一个简单的图书管理程序
    教你如何一键退出USB设备(转)
    四种方法处理“无法停止通用卷设备”(转)
    简单数据恢复菜鸟教程 (转)
    安装flash纠结
    java:文本I/O实例
    数据结构之链表(1)
    win7屏幕录制软件psr.exe使用教程(转)
    SQL:基本知识
    .Net Micro Framework研究—FAT文件系统实现探索
  • 原文地址:https://www.cnblogs.com/makelu/p/11060420.html
Copyright © 2011-2022 走看看