golang基础断言库与原生测试结合插件库assert的使用

golang基础断言库与原生测试结合插件库assert的使用

包简介

Package assert是一个基础断言库,用于与原生Go测试结合使用。

Build Status GoDoc

安装

使用go get安装:

go get github.com/go-playground/assert

然后在你的代码中导入assert包:

import . "github.com/go-playground/assert/v2"

使用示例

下面是一个完整的使用示例,展示了如何在Go测试中使用assert库:

package whatever

import (
	"errors"
	"testing"
	. "github.com/go-playground/assert/v2"
)

// 自定义错误处理断言函数
func AssertCustomErrorHandler(t testing.TB, errs map[string]string, key, expected string) {
	val, ok := errs[key]

	// 使用EqualSkip和NotEqualSkip作为构建自定义Assert函数的基石
	EqualSkip(t, 2, ok, true)
	NotEqualSkip(t, 2, val, nil)
	EqualSkip(t, 2, val, expected)
}

func TestEqual(t *testing.T) {
	// 测试错误断言
	err := errors.New("my error")
	NotEqual(t, err, nil)          // 断言err不等于nil
	Equal(t, err.Error(), "my error") // 断言错误消息匹配

	err = nil
	Equal(t, err, nil)  // 断言err等于nil

	// 测试panic断言
	fn := func() {
		panic("omg omg omg!")
	}

	PanicMatches(t, func() { fn() }, "omg omg omg!") // 断言函数会panic且消息匹配
	PanicMatches(t, func() { panic("omg omg omg!") }, "omg omg omg!")

	// 测试自定义断言函数
	errs := map[string]string{}
	errs["Name"] = "User Name Invalid"
	errs["Email"] = "User Email Invalid"

	AssertCustomErrorHandler(t, errs, "Name", "User Name Invalid")
	AssertCustomErrorHandler(t, errs, "Email", "User Email Invalid")
}

主要功能说明

  1. 基本断言

    • Equal(t, a, b) - 断言a等于b
    • NotEqual(t, a, b) - 断言a不等于b
  2. 错误处理

    • 可以断言错误是否为nil
    • 可以断言错误消息是否匹配预期
  3. Panic测试

    • PanicMatches(t, func(), expected) - 断言函数会panic且panic消息匹配预期
  4. 自定义断言

    • 可以使用EqualSkipNotEqualSkip等基础函数构建更复杂的自定义断言函数

贡献指南

欢迎提交PR贡献代码。如果你创建了有用的自定义断言函数,强烈建议你贡献它们,帮助完善这个包。

许可证

该包基于MIT许可证分发,更多细节请查看代码中的许可证文件。


更多关于golang基础断言库与原生测试结合插件库assert的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang基础断言库与原生测试结合插件库assert的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 测试:基础断言与 assert 库使用指南

在 Go 语言中,标准库提供了基础的测试功能,但有时我们需要更强大的断言功能来简化测试代码。下面我将介绍 Go 原生测试方法和流行的第三方断言库 stretchr/testify/assert 的使用。

1. 原生测试方法

Go 标准库 testing 提供了基础的测试功能,但没有内置断言函数,通常使用 if 判断:

package main

import (
	"testing"
)

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

func TestAdd(t *testing.T) {
	result := Add(2, 3)
	expected := 5
	
	// 原生测试方式
	if result != expected {
		t.Errorf("Add(2, 3) = %d; want %d", result, expected)
	}
	
	// 表驱动测试
	tests := []struct {
		a, b, expected int
	}{
		{1, 2, 3},
		{0, 0, 0},
		{-1, 1, 0},
	}
	
	for _, tt := range tests {
		if got := Add(tt.a, tt.b); got != tt.expected {
			t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, got, tt.expected)
		}
	}
}

2. 使用 testify/assert 库

testify 是一个流行的测试工具包,其中 assert 子包提供了丰富的断言函数。

安装

go get github.com/stretchr/testify/assert

基本用法

package main

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

func TestAddWithAssert(t *testing.T) {
	result := Add(2, 3)
	
	// 基本断言
	assert.Equal(t, 5, result, "它们应该相等")
	
	// 不相等断言
	assert.NotEqual(t, 6, result)
	
	// nil 断言
	var nilVar *int
	assert.Nil(t, nilVar)
	
	// 非 nil 断言
	notNilVar := 1
	assert.NotNil(t, &notNilVar)
	
	// 真值断言
	assert.True(t, result > 0)
	
	// 假值断言
	assert.False(t, result < 0)
	
	// 包含断言 (适用于字符串、数组、map等)
	assert.Contains(t, "Hello World", "World")
	assert.Contains(t, []int{1,2,3}, 2)
	
	// 长度断言
	assert.Len(t, []int{1,2,3}, 3)
	
	// 错误断言
	err := someFunctionThatReturnsError()
	assert.Error(t, err)
	
	// 无错误断言
	noErr := someFunctionThatReturnsNoError()
	assert.NoError(t, noErr)
	
	// 近似相等 (适用于浮点数)
	assert.InDelta(t, 0.5, 0.1+0.4, 0.0001)
}

高级用法

func TestAdvancedAssertions(t *testing.T) {
	// 正则匹配
	assert.Regexp(t, `^[a-z]+\[[0-9]+\]$`, "adam[23]")
	
	// JSON 相等
	expected := `{"name":"John", "age":30}`
	actual := `{"age":30, "name":"John"}`
	assert.JSONEq(t, expected, actual)
	
	// 元素匹配 (顺序无关)
	expectedSlice := []int{1, 2, 3}
	actualSlice := []int{3, 2, 1}
	assert.ElementsMatch(t, expectedSlice, actualSlice)
	
	// 文件存在
	assert.FileExists(t, "/path/to/file")
	
	// 目录存在
	assert.DirExists(t, "/path/to/dir")
	
	// 恐慌断言
	assert.Panics(t, func() {
		panic("test panic")
	})
	
	// 恐慌值断言
	assert.PanicsWithValue(t, "test panic", func() {
		panic("test panic")
	})
}

3. 原生测试与 assert 库对比

特性 原生 testing 包 testify/assert
断言语法 手动 if 判断 丰富的断言函数
错误信息 需要手动编写 自动生成
可读性 一般 优秀
功能丰富度 基础 全面
学习曲线 中等
依赖 需要安装

4. 最佳实践建议

  1. 小型项目:如果项目简单,原生 testing 包可能足够
  2. 中大型项目:推荐使用 assert 库提高测试可读性和开发效率
  3. 表驱动测试:结合 assert 库和表驱动测试可以获得最佳效果
  4. 错误信息:assert 库自动生成的错误信息通常足够详细
  5. 性能考虑:assert 库有轻微性能开销,但对大多数应用影响不大
// 结合表驱动测试和 assert 的示例
func TestTableDrivenWithAssert(t *testing.T) {
	tests := []struct {
		name     string
		a, b     int
		expected int
	}{
		{"positive numbers", 2, 3, 5},
		{"zeros", 0, 0, 0},
		{"negative numbers", -1, -2, -3},
	}
	
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equal(t, tt.expected, Add(tt.a, tt.b))
		})
	}
}

通过使用 assert 库,你可以编写更简洁、更易读的测试代码,同时获得更详细的失败信息,这在调试复杂测试时特别有用。

回到顶部