Go 测试

1. 测试文件的组织

在 Go 中,测试文件通常与被测试的源文件位于同一包内,并遵循以下命名规范:

  • 源文件xxx.go
  • 测试文件xxx_test.go

测试文件的命名必须以 _test.go 结尾,这样 Go 工具链才能识别并将其作为测试文件处理。

2. 测试函数的签名

测试函数必须满足以下签名:

go 复制代码
func TestXxx(t *testing.T) { ... }
  • 函数名以 Test 开头,后面跟被测试的函数或功能名称(通常首字母大写)。
  • 接受一个参数 *testing.T,用于报告测试失败和日志信息。

二、编写测试函数

1. 基本示例

假设有一个简单的加法函数 Add,位于 math.go 文件中:

go 复制代码
// math.go
package mathutil

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

对应的测试文件 math_test.go 可以这样编写:

go 复制代码
// math_test.go
package mathutil

import (
    "testing"
)

func TestAdd(t *testing.T) {
    tests := []struct {
        a, b, expected int
    }{
        {1, 2, 3},
        {0, 0, 0},
        {-1, 1, 0},
    }

    for _, tt := range tests {
        result := Add(tt.a, tt.b)
        if result != tt.expected {
            t.Errorf("Add(%d, %d) = %d; expected %d", tt.a, tt.b, result, tt.expected)
        }
    }
}

2. 使用子测试

Go 1.7 引入了子测试(subtests),使得在同一个测试函数中运行多个相关测试更加方便:

go 复制代码
func TestAdd(t *testing.T) {
    tests := []struct {
        a, b, expected int
    }{
        {1, 2, 3},
        {0, 0, 0},
        {-1, 1, 0},
    }

    for _, tt := range tests {
        t.Run(fmt.Sprintf("%d+%d", tt.a, tt.b), func(t *testing.T) {
            result := Add(tt.a, tt.b)
            if result != tt.expected {
                t.Errorf("Add(%d, %d) = %d; expected %d", tt.a, tt.b, result, tt.expected)
            }
        })
    }
}

3. 使用表驱动测试

表驱动测试是一种常见的测试模式,通过定义一组输入和预期输出来测试函数的行为:

go 复制代码
func TestMultiply(t *testing.T) {
    tests := []struct {
        a, b, expected int
    }{
        {2, 3, 6},
        {0, 5, 0},
        {-2, 4, -8},
    }

    for _, tt := range tests {
        t.Run(fmt.Sprintf("%d*%d", tt.a, tt.b), func(t *testing.T) {
            result := Multiply(tt.a, tt.b)
            if result != tt.expected {
                t.Errorf("Multiply(%d, %d) = %d; expected %d", tt.a, tt.b, result, tt.expected)
            }
        })
    }
}

三、运行测试

1. 使用 go test 命令

在包含测试文件的包目录下,运行以下命令即可执行所有测试:

bash 复制代码
go test

2. 运行特定测试

要运行特定的测试函数,可以使用 -run 参数,支持正则表达式:

arduino 复制代码
go test -run TestAdd

3. 查看详细输出

使用 -v 标志可以查看每个测试函数的详细输出:

bash 复制代码
go test -v

4. 并行运行测试

使用 t.Parallel() 可以让测试函数并行执行,提高测试效率:

scss 复制代码
func TestSomething(t *testing.T) {
    t.Parallel()
    // 测试代码
}

运行测试时,可以使用 -parallel 指定并行执行的测试数量:

bash 复制代码
go test -parallel 4

5.测试覆盖率

  • 使用 go test -cover 查看测试覆盖率。

  • 生成覆盖率文件:

    ini 复制代码
    go test -coverprofile=coverage.out 
    go tool cover -html=coverage.out 

示例:完整的测试流程

以下是一个综合示例,展示如何编写、运行和检查测试覆盖率。

1. 源代码

go 复制代码
// mathutil/math.go
package mathutil

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

func Multiply(a, b int) int {
    return a * b
}

2. 测试代码

go 复制代码
// mathutil/math_test.go
package mathutil

import (
    "testing"
)

func TestAdd(t *testing.T) {
    tests := []struct {
        a, b, expected int
    }{
        {1, 2, 3},
        {0, 0, 0},
        {-1, 1, 0},
    }

    for _, tt := range tests {
        t.Run(fmt.Sprintf("%d+%d", tt.a, tt.b), func(t *testing.T) {
            result := Add(tt.a, tt.b)
            if result != tt.expected {
                t.Errorf("Add(%d, %d) = %d; expected %d", tt.a, tt.b, result, tt.expected)
            }
        })
    }
}

3. 运行测试和覆盖率

ini 复制代码
go test -v -coverprofile=coverage.out
go tool cover -html=coverage.out

Go 提供了强大而简洁的测试工具,使得编写和维护测试变得非常方便。通过合理组织测试文件、编写可测试的代码、以及定期检查测试覆盖率,开发者可以确保代码的质量和可靠性。结合持续集成流程,自动化测试更是保障项目稳定性的重要手段。

相关推荐
我不会起名字3227 小时前
一天一道力扣Hot100(36):深度优先算法---组合总和
数据结构·c++·后端·python·算法·go
名字还没想好☜18 小时前
Go context.AfterFunc 实战(Go 1.21):context 一取消就自动跑清理,告别手写 goroutine 监听 Done
后端·golang·go
liyinchi19882 天前
微信小程序支付遇到“由于小程序违规,支付功能暂时无法使用” 解决办法
java·微信小程序·go
天天喝旺仔2 天前
Go 泛型实战:从类型参数、约束到可复用泛型容器与函数
数据结构·算法·容器·go
gospace3 天前
【无标题】
go·gb28181·gowvp
我不会起名字3223 天前
一天一道算法题(35):电话号码的字母组合
java·数据结构·后端·python·leetcode·go·回溯
江湖十年3 天前
Go GOPROXY 兜底链的坑:从一次诡异的 CI lint 失败说起
后端·面试·go
秋风点枝4 天前
gogogo!go语言感悟大观--打卡day01
go·devops
探索云原生4 天前
KubeClipper 1.7.0 发布:Operation 优化与 Kubernetes 1.37 支持
linux·docker·云原生·kubernetes·go
右耳朵猫AI4 天前
Go周刊2026W37 | Ebitengine 纯 Go 化、simd 重写 TurboPFor、json/v2 落地
后端·微服务·go