test

package
v1.1.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2025 License: MIT Imports: 25 Imported by: 0

README

Flow 测试工具

Flow 测试工具提供了一套完整的测试支持库,帮助开发者轻松编写单元测试和集成测试。这些工具旨在简化测试过程,提高测试代码的可读性和可维护性。

目录结构

test/
├── helper.go       # 通用测试助手函数
├── http.go         # HTTP测试客户端
├── mock.go         # 模拟数据生成工具
├── unit.go         # 单元测试支持
├── integration.go  # 集成测试支持
├── fixtures/       # 测试数据文件
│   └── users.json  # 用户测试数据示例
└── example_test.go # 使用示例

主要功能

1. 测试助手 (Helper)

Helper 提供通用的测试辅助功能,如临时文件创建、路径解析等。

helper := test.NewHelper(t)

// 获取项目根目录
rootPath := helper.GetProjectRoot()

// 创建临时文件
tmpFile := helper.TempFile("prefix-*.txt", []byte("测试内容"))

// 创建临时目录
tmpDir := helper.TempDir()

// 生成随机字符串
randomStr := helper.RandomString(10)
2. HTTP测试客户端 (HTTPClient)

HTTPClient 简化了API测试过程,提供了一种流畅的方式来模拟HTTP请求和验证响应。

// 创建HTTP测试客户端
client := test.NewHTTPClient(t, app)

// 发送GET请求
response := client.GET("/api/users", nil, nil)

// 验证响应
response.AssertStatus(t, 200)
response.AssertJSONContains(t, "message", "操作成功")

// 发送POST请求
response = client.POST("/api/users", user, nil)

// 绑定响应到结构体
var result UserResponse
response.BindJSON(&result)
3. 模拟数据生成 (MockGenerator)

MockGenerator 用于生成各种类型的随机测试数据,特别适合填充实体对象。

// 创建模拟数据生成器
gen := test.NewMockGenerator()

// 生成随机基本类型
randomInt := gen.RandomInt(1, 100)
randomFloat := gen.RandomFloat(1.0, 100.0)
randomBool := gen.RandomBool()
randomString := gen.RandomString(10)
randomEmail := gen.RandomEmail()
randomName := gen.RandomName()
randomDate := gen.RandomDate(2000, 2023)
randomPhone := gen.RandomPhoneNumber()

// 自动填充结构体
var user User
gen.FillStruct(&user)
4. 单元测试支持 (UnitTest)

UnitTest 提供单元测试相关功能,简化测试编写和断言过程。

// 创建单元测试助手
ut := test.NewUnitTest(t)

// 获取测试函数名称
testName := ut.GetTestName()

// JSON 转换
jsonStr := ut.ToJSON(obj)
ut.FromJSON(jsonStr, &result)
ut.AssertJSONEqual(expected, actual)

// 运行测试用例
ut.RunTestCase("测试用例1", func(t *testing.T) {
    // 测试代码
})
5. 模拟对象 (Mock)

Mock 用于创建模拟对象,记录方法调用并进行验证。

// 创建模拟对象
mock := test.NewMock()

// 记录方法调用
mock.RecordCall("MethodName", arg1, arg2)

// 验证方法调用
mockAssert := test.NewMockAssertions(t, mock)
mockAssert.AssertCalled("MethodName", arg1, arg2)
mockAssert.AssertNotCalled("OtherMethod")
mockAssert.AssertCalledTimes("MethodName", 2)
6. 集成测试支持 (IntegrationTest)

IntegrationTest 提供一套工具,用于进行依赖于数据库和外部服务的集成测试。

// 创建集成测试助手
it := test.NewIntegrationTest(t)

// 设置测试应用
app := it.SetupTestApp()

// 设置测试数据库
db := it.SetupTestDB()

// 创建测试表
it.MigrateTestModels(&User{}, &Product{})

// 清空表数据
it.TruncateTable("users")

// 创建测试数据
it.CreateTestFixtures("users.json", &User{})

// 执行SQL
it.ExecuteSQL("UPDATE users SET status = ? WHERE id = ?", "active", 1)

// HTTP 测试
client := it.NewHTTPTest()
response := client.GET("/api/users", nil, nil)

// 事务测试
tx := it.SetupTestTransaction()

使用示例

详细示例可参考 example_test.go 文件,其中包含了单元测试和集成测试的完整示例。

最佳实践

  1. 隔离测试环境: 集成测试应使用独立的测试数据库,避免影响开发环境
  2. 合理使用模拟: 单元测试中通过模拟外部依赖,专注于测试单个组件的功能
  3. 使用测试数据文件: 将测试数据存储在 fixtures 目录,便于维护和复用
  4. 测试边界条件: 除了正常场景,也要测试各种错误情况和边界条件
  5. 保持测试独立: 每个测试应该能够独立运行,不依赖其他测试的结果

注意事项

  • 集成测试通常较慢,可以通过环境变量或命令行标志来控制是否运行
  • 尽量使用测试工具提供的辅助函数,减少重复代码
  • 测试失败时提供有意义的错误消息,便于定位问题

Documentation

Overview

Package test 提供测试支持工具和辅助函数

Package test 提供测试支持工具和辅助函数

Package test 提供测试支持工具和辅助函数

Package test 提供测试支持工具和辅助函数

Package test 提供测试支持工具和辅助函数

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RunIntegrationTests

func RunIntegrationTests(t *testing.T, suite IntegrationTestSuite, tests map[string]func(t *testing.T))

RunIntegrationTests 运行集成测试套件中的测试

Types

type HTTPClient

type HTTPClient struct {
	Engine  *flow.Engine
	T       *testing.T
	BaseURL string
	Headers map[string]string
}

HTTPClient 是用于测试HTTP请求的客户端

func NewHTTPClient

func NewHTTPClient(t *testing.T, engine *flow.Engine) *HTTPClient

NewHTTPClient 创建一个新的HTTP测试客户端

func (*HTTPClient) DELETE

func (c *HTTPClient) DELETE(path string, headers map[string]string) *Response

DELETE 发送DELETE请求

func (*HTTPClient) Do

func (c *HTTPClient) Do(req Request) *Response

Do 执行HTTP请求并返回响应

func (*HTTPClient) GET

func (c *HTTPClient) GET(path string, query url.Values, headers map[string]string) *Response

GET 发送GET请求

func (*HTTPClient) PATCH

func (c *HTTPClient) PATCH(path string, body interface{}, headers map[string]string) *Response

PATCH 发送PATCH请求

func (*HTTPClient) POST

func (c *HTTPClient) POST(path string, body interface{}, headers map[string]string) *Response

POST 发送POST请求

func (*HTTPClient) PUT

func (c *HTTPClient) PUT(path string, body interface{}, headers map[string]string) *Response

PUT 发送PUT请求

func (*HTTPClient) UploadFile

func (c *HTTPClient) UploadFile(path, fieldName, filePath string, additionalFields map[string]string) *Response

UploadFile 上传文件测试辅助函数

func (*HTTPClient) WithBaseURL

func (c *HTTPClient) WithBaseURL(baseURL string) *HTTPClient

WithBaseURL 设置基础URL

func (*HTTPClient) WithHeader

func (c *HTTPClient) WithHeader(key, value string) *HTTPClient

WithHeader 添加请求头

func (*HTTPClient) WithHeaders

func (c *HTTPClient) WithHeaders(headers map[string]string) *HTTPClient

WithHeaders 批量添加请求头

type Helper

type Helper struct {
	T *testing.T
}

Helper 测试助手结构

func NewHelper

func NewHelper(t *testing.T) *Helper

NewHelper 创建一个新的测试助手实例

func (*Helper) AssertContainsAll

func (h *Helper) AssertContainsAll(str string, substrings ...string)

AssertContainsAll 断言一个字符串包含所有指定的子字符串

func (*Helper) AssertNotContainsAny

func (h *Helper) AssertNotContainsAny(str string, substrings ...string)

AssertNotContainsAny 断言一个字符串不包含任何指定的子字符串

func (*Helper) CleanupTestDB

func (h *Helper) CleanupTestDB(db *gorm.DB)

CleanupTestDB 清理测试数据库

func (*Helper) GetProjectRoot

func (h *Helper) GetProjectRoot() string

GetProjectRoot 获取项目根目录路径

func (*Helper) LoadFixtureFile

func (h *Helper) LoadFixtureFile(relativePath string) []byte

LoadFixtureFile 加载测试数据文件

func (*Helper) RandomString

func (h *Helper) RandomString(length int) string

RandomString 生成指定长度的随机字符串

func (*Helper) RunParallel

func (h *Helper) RunParallel(fn func(h *Helper))

RunParallel 并行运行测试函数

func (*Helper) SetupAndTeardown

func (h *Helper) SetupAndTeardown(setup func(), teardown func())

SetupAndTeardown 设置测试的前置和后置处理

func (*Helper) SetupTestDB

func (h *Helper) SetupTestDB() *gorm.DB

SetupTestDB 设置测试数据库连接 注意:此函数仅为示例,实际实现需要进行适当修改 通常的实现方式为: 1. 创建临时数据库文件 2. 构建数据库连接字符串 3. 建立数据库连接 4. 根据需要进行数据库初始化

func (*Helper) TempDir

func (h *Helper) TempDir() string

TempDir 创建临时目录并返回其路径,测试完成后会自动清理

func (*Helper) TempFile

func (h *Helper) TempFile(pattern string, content []byte) string

TempFile 创建临时文件并返回其路径,测试完成后会自动清理

type IntegrationTest

type IntegrationTest struct {
	T         *testing.T
	App       *flow.Engine
	TestDB    *gorm.DB
	Helper    *Helper
	SQLiteDSN string
}

IntegrationTest 提供集成测试支持

func NewIntegrationTest

func NewIntegrationTest(t *testing.T) *IntegrationTest

NewIntegrationTest 创建一个新的集成测试助手

func (*IntegrationTest) CreateFixturesDir

func (i *IntegrationTest) CreateFixturesDir() string

CreateFixturesDir 创建测试数据文件目录

func (*IntegrationTest) CreateTestFixtures

func (i *IntegrationTest) CreateTestFixtures(fixturePath string, modelType interface{})

CreateTestFixtures 从文件创建测试数据

func (*IntegrationTest) ExecuteSQL

func (i *IntegrationTest) ExecuteSQL(query string, args ...interface{})

ExecuteSQL 执行原始SQL查询

func (*IntegrationTest) MigrateTestModels

func (i *IntegrationTest) MigrateTestModels(models ...interface{})

MigrateTestModels 为测试模型创建数据库表

func (*IntegrationTest) NewHTTPTest

func (i *IntegrationTest) NewHTTPTest() *HTTPClient

NewHTTPTest 创建用于HTTP测试的客户端

func (*IntegrationTest) RunWithTimeout

func (i *IntegrationTest) RunWithTimeout(timeout time.Duration, fn func(ctx context.Context))

RunWithTimeout 在指定超时时间内运行测试函数

func (*IntegrationTest) SetupRepositoryWithTx

func (i *IntegrationTest) SetupRepositoryWithTx(modelType interface{}) *db.GenericRepository[interface{}]

SetupRepositoryWithTx 使用事务设置仓储 这是一个通用示例,实际使用时需要根据项目的仓储实现进行调整

func (*IntegrationTest) SetupTestApp

func (i *IntegrationTest) SetupTestApp() *flow.Engine

SetupTestApp 设置测试应用

func (*IntegrationTest) SetupTestDB

func (i *IntegrationTest) SetupTestDB() *gorm.DB

SetupTestDB 设置测试数据库

func (*IntegrationTest) SetupTestTransaction

func (i *IntegrationTest) SetupTestTransaction() *sql.Tx

SetupTestTransaction 开始一个测试事务

func (*IntegrationTest) TruncateTable

func (i *IntegrationTest) TruncateTable(tableName string)

TruncateTable 清空数据表中的数据

type IntegrationTestSuite

type IntegrationTestSuite interface {
	SetupSuite(t *testing.T)
	TeardownSuite()
	SetupTest(t *testing.T)
	TeardownTest()
}

IntegrationTestSuite 集成测试套件接口

type Mock

type Mock struct {
	Calls map[string][][]interface{}
}

Mock 是单元测试中的模拟对象基类

func NewMock

func NewMock() *Mock

NewMock 创建一个新的模拟对象

func (*Mock) CallCount

func (m *Mock) CallCount(methodName string) int

CallCount 获取特定方法被调用的次数

func (*Mock) GetCalls

func (m *Mock) GetCalls(methodName string) [][]interface{}

GetCalls 获取对特定方法的所有调用

func (*Mock) RecordCall

func (m *Mock) RecordCall(methodName string, args ...interface{})

RecordCall 记录对模拟对象的方法调用

func (*Mock) WasCalled

func (m *Mock) WasCalled(methodName string) bool

WasCalled 判断特定方法是否被调用过

type MockAssertions

type MockAssertions struct {
	T    *testing.T
	Mock *Mock
}

MockAssertions 提供对模拟对象的断言

func NewMockAssertions

func NewMockAssertions(t *testing.T, mock *Mock) *MockAssertions

NewMockAssertions 创建新的模拟断言助手

func (*MockAssertions) AssertCalled

func (a *MockAssertions) AssertCalled(methodName string, args ...interface{}) bool

AssertCalled 断言方法已被调用

func (*MockAssertions) AssertCalledTimes

func (a *MockAssertions) AssertCalledTimes(methodName string, times int) bool

AssertCalledTimes 断言方法被调用特定次数

func (*MockAssertions) AssertNotCalled

func (a *MockAssertions) AssertNotCalled(methodName string) bool

AssertNotCalled 断言方法未被调用

type MockGenerator

type MockGenerator struct {
	// contains filtered or unexported fields
}

MockGenerator 提供用于测试的数据生成功能

func NewMockGenerator

func NewMockGenerator() *MockGenerator

NewMockGenerator 创建一个新的模拟数据生成器

func (*MockGenerator) FillStruct

func (g *MockGenerator) FillStruct(s interface{})

FillStruct 使用随机数据填充结构体

func (*MockGenerator) RandomBool

func (g *MockGenerator) RandomBool() bool

RandomBool 生成随机布尔值

func (*MockGenerator) RandomDate

func (g *MockGenerator) RandomDate(startYear, endYear int) time.Time

RandomDate 生成指定范围内的随机日期

func (*MockGenerator) RandomElement

func (g *MockGenerator) RandomElement(slice interface{}) interface{}

RandomElement 从切片中随机选择一个元素

func (*MockGenerator) RandomEmail

func (g *MockGenerator) RandomEmail() string

RandomEmail 生成随机邮箱

func (*MockGenerator) RandomFloat

func (g *MockGenerator) RandomFloat(min, max float64) float64

RandomFloat 生成指定范围内的随机浮点数

func (*MockGenerator) RandomInt

func (g *MockGenerator) RandomInt(min, max int) int

RandomInt 生成指定范围内的随机整数

func (*MockGenerator) RandomName

func (g *MockGenerator) RandomName() string

RandomName 生成随机姓名

func (*MockGenerator) RandomPhoneNumber

func (g *MockGenerator) RandomPhoneNumber() string

RandomPhoneNumber 生成随机手机号

func (*MockGenerator) RandomString

func (g *MockGenerator) RandomString(length int) string

RandomString 生成指定长度的随机字符串

func (*MockGenerator) RandomSubset

func (g *MockGenerator) RandomSubset(slice interface{}, n int) interface{}

RandomSubset 从切片中随机选择n个元素

func (*MockGenerator) WithSeed

func (g *MockGenerator) WithSeed(seed int64) *MockGenerator

WithSeed 使用固定种子初始化随机数生成器,用于生成可重现的数据

type Request

type Request struct {
	Method  string
	Path    string
	Headers map[string]string
	Body    interface{}
	Query   url.Values
}

Request 定义HTTP请求结构

type Response

type Response struct {
	StatusCode int
	Header     http.Header
	Body       []byte
	Result     interface{}
	Raw        *httptest.ResponseRecorder
}

Response 定义HTTP响应结构

func (*Response) AssertHeader

func (r *Response) AssertHeader(t *testing.T, key, value string) *Response

AssertHeader 断言Header等于指定值

func (*Response) AssertHeaderContains

func (r *Response) AssertHeaderContains(t *testing.T, key, value string) *Response

AssertHeaderContains 断言Header包含指定值

func (*Response) AssertJSON

func (r *Response) AssertJSON(t *testing.T, expected interface{}) *Response

AssertJSON 断言JSON响应

func (*Response) AssertJSONContains

func (r *Response) AssertJSONContains(t *testing.T, key string, value interface{}) *Response

AssertJSONContains 断言JSON响应中包含指定字段

func (*Response) AssertStatus

func (r *Response) AssertStatus(t *testing.T, status int) *Response

AssertStatus 断言HTTP状态码

func (*Response) BindJSON

func (r *Response) BindJSON(v interface{}) error

BindJSON 将响应体绑定到JSON结构

func (*Response) JSON

func (r *Response) JSON() (map[string]interface{}, error)

JSON 返回响应体解析为JSON的结果

func (*Response) String

func (r *Response) String() string

String 返回响应体的字符串表示

type UnitTest

type UnitTest struct {
	T *testing.T
}

UnitTest 提供单元测试支持

func NewUnitTest

func NewUnitTest(t *testing.T) *UnitTest

NewUnitTest 创建一个新的单元测试助手

func (*UnitTest) AssertJSONEqual

func (u *UnitTest) AssertJSONEqual(expected, actual string)

AssertJSONEqual 断言两个JSON字符串相等

func (*UnitTest) CallMethod

func (u *UnitTest) CallMethod(obj interface{}, methodName string, args ...interface{}) []interface{}

CallMethod 调用对象的方法并返回结果

func (*UnitTest) FromJSON

func (u *UnitTest) FromJSON(jsonStr string, obj interface{})

FromJSON 将JSON字符串转换为对象

func (*UnitTest) GetFunctionName

func (u *UnitTest) GetFunctionName(i interface{}) string

GetFunctionName 获取函数的名称(用于测试函数名称)

func (*UnitTest) GetTestName

func (u *UnitTest) GetTestName() string

GetTestName 从测试函数获取测试名称

func (*UnitTest) RunTestCase

func (u *UnitTest) RunTestCase(name string, fn func(t *testing.T))

RunTestCase 运行单个测试用例

func (*UnitTest) RunTestCases

func (u *UnitTest) RunTestCases(testCases map[string]func(t *testing.T))

RunTestCases 运行多个测试用例

func (*UnitTest) ToJSON

func (u *UnitTest) ToJSON(obj interface{}) string

ToJSON 将对象转换为JSON字符串

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL