Go 语言单元测试 - 入门篇

go 语言发展非常迅速,大家对go语言编程也比较熟悉了,但很多同学对于go语言的测试不太熟悉,最近准备三篇关于Go语言的测试文章来介绍Go语言的测试相关内容。

单元测试框架

go语言提供了编写go语言的自动化测试框架testing.T,testing.B等,我们通过go test命令就可以来启动测试。我们编写测试方法的格式如下:

func TestXxx(*testing.T)

注意这里的方法名TestXxx中第一个X是大写,这是一种推荐的规范。测试方法名在实际方法名Xxx前加Test标明这是测试Xxx的方法。

另外,我们推荐将测试文件取名xxx_test.go这样的格式,其中xxx为go源文件的名称,方便我们定位某个文件的测试文件。go测试文件和源文件放在同一个目录下。该文件将从常规软件包构建中排除,但在运行go test命令时将包含该文件。

单元测试编写规范

单元测试通常都是通过一组用例数据,作为方法的参数传入,检查输出是否与预期的返回值相同。这种思路也适用于Go语言,只不过在实现形式上推荐采用更为优雅的方式。

假设我们有一个非常简单的helper.go, 实现两个整数相加输出结果的功能,实现代码如下:

package helper

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

我们可以写如下的测试代码:

package helper

import (
    "testing"
)

func TestAdd(t *testing.T) {
    var param1 = 1
    var param2 = 1
    var result = 2
    r := Add(param1, param2)
    if r != result {
        if r != result {
            t.Errorf("error: expecte %d, but got %d", result, r)
        }
    }
}

这个代码这样写并没有什么大的问题,如果考虑其扩展性,比如增加新的测试场景(代码在不断迭代优化中),代码的可读性就会变得越来越差,如何有效确保扩展性的前提下不降低可读性呢?推荐如下方式:

package helper

import (
    "testing"
)

func TestAdd(t *testing.T) {
    tests := []struct {
        param1 int
        param2 int
        result int
    }{
        {
            param1: 1,
            param2: 1,
            result: 2,
        },
    }

    for _, test := range tests {
        r := Add(test.param1, test.param2)
        if r != test.result {
            t.Errorf("error: expecte %d, but got %d", test.result, r)
        }
    }
}

这种方式下,测试代码更加简洁,在增加新的测试场景的情况下,也不会降低可读性,这种设计在Kubernetes及阿里Pouch等开源项目中都有此类实践,大家可以关注。

特殊功能开关

指定运行的方式

可以通过go test -run xxx的形式来指定运行的方法,注意这里的run参数是正则匹配的,如下所示:

bogon:helper $ go test -v
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
=== RUN   TestExp
--- PASS: TestExp (0.00s)
PASS
ok      demo/helper 0.005s
bogon:helper $ go test -run TestAdd -v
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok      demo/helper 0.005s
bogon:helper $ go test -run TestExp -v
=== RUN   TestExp
--- PASS: TestExp (0.00s)
PASS
ok      demo/helper 0.005s

获取测试覆盖率

go 提供了获取单元测试覆盖率参数,执行如下命令:

go test -v -coverprofile cover.out
go tool cover -html=cover.out -o cover.html

我们打开cover.html就可以获得单元测试覆盖率信息,如下所示:

这里写图片描述

限制同时执行的线程数

go语言有一个GOMAXPROCS变量,可以指定运行Go代码的操作系统线程数。如果执行时不加该参数,则就是当前所设置的GOMAXPROCS值。

bogon:helper $ go test -cpu 1
PASS
ok      demo/helper 0.005s

总结

Go语言是一个严禁且高效的开发语言,在单元测试方面,提供了很多好的工程实践,这些思想可以在其他语言中采用,这一篇是一个开始,后续会介绍Go语言测试的Benchmark部分,主要是针对性能相关部分的内容。

猜你喜欢

转载自blog.csdn.net/afandaafandaafanda/article/details/82736831