美文网首页
golang 单元测试(一)

golang 单元测试(一)

作者: jssyjam | 来源:发表于2019-04-18 12:04 被阅读0次

    单元测试函数类型

    Test(功能测试)

    函数规则:

    • 函数名: TestXxxx , 以Test为前缀。Xxxx以大写字母开头
    • 参数类型: *testing.T
    func TestXxxx(t *testing.T){...}
    

    编写一个简单的例子,假设有下面一个待测函数:

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

    测试代码如下:

    import "testing"
    
    func TestAdd(t *testing.T) {
        cases := []struct {
            first    int
            second   int
            excepted int
        }{
            {1, 2, 3},
            {1, 2, 4},
        }
    
        for _, c := range cases {
            result := add(c.first, c.second)
            if result != c.excepted {
                t.Fatalf("add function failed, first: %d, second:%d, execpted:%d, result:%d", c.first, c.second, c.excepted, result)
            }
        }
    }
    

    执行 go go test -v 结果如下:

    === RUN   TestAdd
    --- FAIL: TestAdd (0.00s)
        example_test.go:30: add function failed, first: 1, second:2, execpted:4, result:3
    FAIL
    exit status 1
    FAIL    gotest/gotest   0.006s
    

    第二个测试用例出错,未能通过单元测试,需要检查测试数据或者被测试函数是否符合我们的预期。

    从上述过程可以看出, TestXxxx 可以理解为功能性测试,其目的在于测试函数的功能性是否正确, 应当编写尽可能多的测试用例来验证被测函数的正确性。

    Benchmark(基准测试)

    函数规则:

    • 函数名: BenchmarkXxxx, 以Benchmark为前缀。Xxxx以大写字母开头
    • 参数类型: *testing.B
    func BenchmarkXxx(b *testing.B){...}
    

    性能测试函数如下:

    func BenchmarkAdd(b *testing.B) {
        for i := 0; i < b.N; i++ {
            add(1, 2)
        }
    }
    

    执行 go test -bench=. -run=^$,结果如下:

    goos: darwin
    goarch: amd64
    pkg: gotest/gotest
    BenchmarkAdd-8      2000000000           0.32 ns/op
    PASS
    ok      gotest/gotest   0.667s
    

    测试结果说明:

    • -8 表示 8个逻辑cpu个数(下文会解释)
    • 2000000000 表示执行了 2000000000 次
    • 0.32 ns/op 每次操作耗时
    • 0.667s 是总时长

    性能测试函数计时器:

    当性能测试函数中有一些额外的初始化操作时,可以通过启停计时器来屏蔽这些操作对最终性能测试的影响。简单例子如下:

    func BenchmarkAdd(b *testing.B) {
        time.Sleep(10 * time.Second)
        for i := 0; i < b.N; i++ {
            add(1, 2)
        }
    }
    

    执行命令go test -bench=.,结果如下:

    goos: darwin
    goarch: amd64
    pkg: gotest/gotest
    BenchmarkAdd-8             1    10004479538 ns/op
    PASS
    ok      gotest/gotest   10.011s
    

    单个测试函数耗时为 10004479538 ns,同时我们也可以看到,这个函数执行一次就已经达到了最大上限时间。

    加上时间计数器:

    func BenchmarkAdd(b *testing.B) {
        b.StopTimer()
        time.Sleep(10 * time.Second)
        b.StartTimer()
        for i := 0; i < b.N; i++ {
            add(1, 2)
        }
    }
    

    测试结果如下:

    goos: darwin
    goarch: amd64
    pkg: gotest/gotest
    BenchmarkAdd-8      2000000000           0.34 ns/op
    PASS
    ok      gotest/gotest   60.751s
    

    单次执行耗时为: 0.34 ns 了。

    Tips:

    对于 b.N 参数而言, test 命令先会尝试设置为1,之后执行函数。如果测试函数没有达到执行上限的话, test 函数会增大,之后再次执行测试函数,如此往复,直到执行时间大于或者等于上限时间为止。 上限时间可以使用 -benchtime设定

    Example(示例测试)

    函数规则:

    • 函数名: ExampleXxx
    • 输出内容至标准输出,参数列表没有限制

    示例测试函数如下:

    func Println(content string) {
        fmt.Println("The output of\nthis example.")
    }
    func ExamplePrintln() {
        Println("The output of\nthis example.")
        // Output: The output of
        // this example.
    }
    

    go test 命令会检测实际输出与注释中的期望输出是否一致, 一致则测试通过,不一致则测试失败。

    go test 常用参数

    • -cpu: 设置测试最大 cpu 逻辑数(也就是 GPM 中 P, 最大并行执行的 gorouting 数量, 默认等于 cpu 核数)
    • -count: 设置执行测试函数的次数, 默认为 1
    • -run: 执行功能测试函数, 支持正则匹配, 可以选择测试函数或者测试文件来仅测试单个函数或者单个文件
    • -bench: 执行基准测试函数, 支持正在匹配
    • -benchtime: 基准测试最大探索时间上限
    • -parallel: 设置同一个被测试代码包中的功能测试函数的最大并发执行数
    • -v: 是展示测试过程信息

    更多的参数可以参考下文的官方文档

    参考

    golang 官方文档

    极客时间

    相关文章

      网友评论

          本文标题:golang 单元测试(一)

          本文链接:https://www.haomeiwen.com/subject/ghvzwqtx.html