Skip to content

第三方测试库 ​

testing 包够用但朴素:断言要手写 if + t.Errorf,打桩、BDD、模糊测试这些它都没有。下面五个第三方库各补一块短板,按需挑选。

6.1 testify ​

testify 是一个流行的 Go 测试库,提供了断言、模拟和套件功能,使测试更易于编写和维护。

主要特性:

  • 断言(Assertions):提供丰富的断言方法,例如 Equal, NotNil, Contains 等。
  • 模拟(Mocking):支持生成模拟对象并定义预期行为。
  • 套件(Suites):支持使用测试套件来组织测试代码。

安装:

sh
go get github.com/stretchr/testify

使用示例:

go
// example_test.go
package example

import (
    "testing"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/mock"
)

// Service 接口及其模拟
type Service interface {
    DoSomething() string
}

type MockService struct {
    mock.Mock
}

func (m *MockService) DoSomething() string {
    args := m.Called()
    return args.String(0)
}

// 测试示例
func TestService(t *testing.T) {
    mockService := new(MockService)
    mockService.On("DoSomething").Return("Mocked Response")

    result := mockService.DoSomething()
    assert.Equal(t, "Mocked Response", result, "The response should be 'Mocked Response'")
}

6.2 gomock ​

gomock 是 Go 官方支持的一个模拟库,提供了生成和控制模拟对象的功能。它与 mockgen 工具集成,可以从接口生成模拟代码(示例中的 NewMockService 函数即由 mockgen 生成)。

注:github.com/golang/mock 已归档,目前维护的分支为 go.uber.org/mock,API 兼容,安装命令为 go install go.uber.org/mock/mockgen@latest,导入路径为 go.uber.org/mock/gomock。

主要特性:

  • 模拟代码由 mockgen 从接口生成,预期行为用 EXPECT() 逐条声明。
  • 与 go test 集成良好。

安装:

sh
go get github.com/golang/mock/gomock

使用示例:

go
// example_test.go
package example

import (
    "testing"
    "github.com/golang/mock/gomock"
)

// Service 接口及其模拟
type Service interface {
    DoSomething() string
}

// 测试示例
func TestService(t *testing.T) {
    ctrl := gomock.NewController(t)
    defer ctrl.Finish()

    mockService := NewMockService(ctrl)
    mockService.EXPECT().DoSomething().Return("Mocked Response")

    result := mockService.DoSomething()
    if result != "Mocked Response" {
        t.Errorf("Expected 'Mocked Response', got '%s'", result)
    }
}

6.3 goconvey ​

goconvey 是一个测试框架,提供了增强的断言和 BDD(行为驱动开发)风格的语法,使测试代码更加易读和组织良好。

主要特性:

  • BDD 风格:Convey 嵌套块对应"给定/当/那么",测试结构一眼可读。
  • 断言:So(result, ShouldEqual, 5) 这类声明式写法,失败时输出实际值与期望值。

安装:

sh
go get github.com/smartystreets/goconvey

使用示例:

go
// example_test.go
package example

import (
    "testing"
    . "github.com/smartystreets/goconvey/convey"
)

// 测试示例
func TestAddition(t *testing.T) {
    Convey("Given two integers", t, func() {
        a := 2
        b := 3

        Convey("When added", func() {
            result := a + b

            Convey("The result should be correct", func() {
                So(result, ShouldEqual, 5)
            })
        })
    })
}

6.4 go-fuzz ​

go-fuzz 是一个模糊测试工具,用于发现程序中的潜在错误和漏洞。它通过生成大量随机输入数据来测试程序的鲁棒性。

主要特性:

  • 自动生成测试输入:生成随机或特定模式的输入数据,测试程序的健壮性。
  • 发现潜在缺陷:帮助发现代码中的边界情况和潜在错误。

安装:

sh
go get github.com/dvyukov/go-fuzz

使用示例:

go
// fuzz.go
package example

func Fuzz(data []byte) int {
    // 对数据进行处理,测试程序的鲁棒性
    if len(data) > 0 {
        _ = string(data)
    }
    return 0
}

运行模糊测试:

sh
# 先用 go-fuzz-build 生成模糊测试用的压缩包
go-fuzz-build
# 再用 go-fuzz 运行,-bin 指向上一步生成的压缩包
go-fuzz -bin=example-fuzz.zip

注:Go 1.18+ 已内置原生模糊测试,推荐使用 go test -fuzz=Fuzz,无需安装第三方工具。

6.5 testcontainers-go ​

testcontainers-go 是一个库,用于在测试中启动和管理 Docker 容器,以提供隔离的测试环境。

主要特性:

  • Docker 容器管理:在测试中启动和停止 Docker 容器。
  • 提供隔离环境:确保测试在一致的环境中运行。

安装:

sh
go get github.com/testcontainers/testcontainers-go

使用示例:

go
// example_test.go
package example

import (
    "context"
    "testing"
    "github.com/testcontainers/testcontainers-go"
)

// 测试示例
func TestWithDocker(t *testing.T) {
    ctx := context.Background()
    req := testcontainers.ContainerRequest{
        Image: "redis:latest",
        ExposedPorts: []string{"6379/tcp"},
    }
    redisContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
        ContainerRequest: req,
        Started:          true,
    })
    if err != nil {
        t.Fatalf("Failed to start container: %v", err)
    }
    defer redisContainer.Terminate(ctx)

    // 进行测试
}

总结 ​

五个库各管一段:testify 补断言和 mock,gomock 从接口生成打桩代码,goconvey 提供 BDD 写法,go-fuzz 做模糊测试(Go 1.18 起用内置的 go test -fuzz 即可),testcontainers-go 在 Docker 里起真实依赖跑集成测试。从 testify 开始最省事,其余按项目需要再加。

参考资料 ​

同层页面 ​

相关页面 ​

Hello Golang