golang简单快照测试框架插件库cupaloy的使用
Golang简单快照测试框架插件库cupaloy的使用
概述
cupaloy是一个非常简单的Go快照测试库:它会为你的测试输出创建快照,并与提交的测试快照进行比较。如果值不匹配,测试将会失败。
你不需要手动管理快照文件:只需在测试中使用cupaloy.SnapshotT(t, value)
函数,cupaloy会自动找到相关的快照文件(基于测试名称)并与给定值进行比较。
使用方法
编写测试
首先,编写一个生成输出的测试用例,并将此输出传递给cupaloy.SnapshotT
:
func TestParsing(t *testing.T) {
ast := ParseFile("test_input")
// 检查结果是否与上次更新快照时相同
// 如果结果发生变化(例如因为解析器的行为发生了变化)
// 测试将失败并显示包含更改差异的错误
cupaloy.SnapshotT(t, ast)
}
第一次运行此测试时,将自动创建一个快照(使用github.com/davecgh/go-spew包)。
更新快照
当你的软件行为发生变化导致快照更改时,此测试将开始失败,并显示一个错误,显示新旧快照之间的差异。一旦你确认新快照是正确的(而不是意外更改),你可以通过设置UPDATE_SNAPSHOTS
环境变量并重新运行测试来保存新快照:
UPDATE_SNAPSHOTS=true go test ./...
这将更新所有快照文件以反映代码的当前输出。
支持的格式
你的测试输出的最重要属性是它是确定性的:如果你的输出包含时间戳或其他每次运行都会更改的字段,那么cupaloy会检测到这一点并导致测试失败。
更多示例
表驱动测试
var testCases = map[string][]string{
"TestCaseOne": []string{......},
"AnotherTestCase": []string{......},
....
}
func TestCases(t *testing.T) {
for testName, args := range testCases {
t.Run(testName, func(t *testing.T) {
result := functionUnderTest(args...)
cupaloy.SnapshotT(t, result)
})
}
}
更改输出目录
func TestSubdirectory(t *testing.T) {
result := someFunction()
snapshotter := cupaloy.New(cupaloy.SnapshotSubdirectory("testdata"))
err := snapshotter.Snapshot(result)
if err != nil {
t.Fatalf("error: %s", err)
}
}
调试
Windows注意事项
需要注意的是,Windows上的git可能配置为在检出时将\n
替换为\r\n
(在GitHub Actions上就是这种情况)。在这种情况下,快照看起来相同,但测试会失败。请确保git在所有地方都正确配置。
更多关于golang简单快照测试框架插件库cupaloy的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang简单快照测试框架插件库cupaloy的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 快照测试框架 Cupaloy 使用指南
Cupaloy 是一个简单易用的 Golang 快照测试框架,它可以帮助你快速验证函数的输出是否符合预期。下面我将详细介绍如何使用 Cupaloy 进行快照测试。
安装 Cupaloy
首先安装 Cupaloy 包:
go get github.com/bradleyjkemp/cupaloy
基本用法
简单示例
package main
import (
"testing"
"github.com/bradleyjkemp/cupaloy"
)
func TestStringOutput(t *testing.T) {
result := "Hello, World!"
cupaloy.SnapshotT(t, result)
}
func TestStructOutput(t *testing.T) {
type Person struct {
Name string
Age int
}
result := Person{
Name: "Alice",
Age: 30,
}
cupaloy.SnapshotT(t, result)
}
工作原理
- 第一次运行测试时,Cupaloy 会创建快照文件(默认在
__snapshots__
目录) - 后续测试运行时,会将输出与快照文件中的内容进行比较
- 如果输出不匹配,测试会失败并显示差异
高级用法
自定义快照目录
func TestWithCustomSnapshotDir(t *testing.T) {
cupaloy := cupaloy.New(cupaloy.SnapshotFileExtension(".snap"))
result := map[string]interface{}{
"key": "value",
"num": 42,
}
cupaloy.SnapshotT(t, result)
}
忽略某些字段
func TestWithFieldIgnores(t *testing.T) {
type Config struct {
APIKey string
Endpoint string
Timeout int
CreatedAt time.Time
}
config := Config{
APIKey: "secret-key",
Endpoint: "https://api.example.com",
Timeout: 30,
CreatedAt: time.Now(),
}
// 忽略 APIKey 和 CreatedAt 字段
cupaloy.New(
cupaloy.FieldsToIgnore("APIKey", "CreatedAt"),
).SnapshotT(t, config)
}
自定义比较器
func TestWithCustomComparator(t *testing.T) {
type Product struct {
ID string
Name string
Price float64
UpdatedAt time.Time
}
product := Product{
ID: "123",
Name: "Laptop",
Price: 999.99,
UpdatedAt: time.Now(),
}
// 自定义比较器忽略时间字段
cupaloy.New(
cupaloy.SnapshotSubset(func(p Product) interface{} {
return struct {
ID string
Name string
Price float64
}{
ID: p.ID,
Name: p.Name,
Price: p.Price,
}
}),
).SnapshotT(t, product)
}
更新快照
当你的代码变更导致快照需要更新时:
- 运行测试时会显示差异
- 删除旧的快照文件或使用
-update
标志重新生成:go test -v ./... -update
最佳实践
-
快照测试适合用于:
- 复杂数据结构的输出验证
- 模板渲染结果
- API响应格式
- CLI工具输出
-
不适合用于:
- 包含随机值或时间戳的输出(除非忽略这些字段)
- 需要精确断言特定值的场景
-
维护建议:
- 定期检查快照测试失败是否是预期的变更
- 不要盲目更新快照,要确认变更是否符合预期
- 为快照测试添加有意义的描述
完整示例
package main
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/bradleyjkemp/cupaloy"
)
func TestAPIHandler(t *testing.T) {
// 创建测试HTTP服务器
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
response := map[string]interface{}{
"status": "success",
"data": map[string]interface{}{
"user": map[string]interface{}{
"id": "user-123",
"name": "John Doe",
"email": "john@example.com",
},
},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
})
// 创建测试请求
req := httptest.NewRequest("GET", "/user", nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, req)
// 解析响应
var response map[string]interface{}
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
t.Fatal(err)
}
// 使用快照测试验证响应
cupaloy.New(
cupaloy.FieldsToIgnore("user.id"), // 忽略ID字段
).SnapshotT(t, response)
}
Cupaloy 提供了一种简单高效的方式来验证代码输出,特别适合那些输出结构复杂但相对稳定的场景。通过合理使用,可以显著减少测试代码的编写和维护工作量。