写单元测试时,断言通常足以说明代码对不对。但进入接口测试、图片测试或模糊测试后,仅有一句“测试失败”往往不够。

开发者可能需要保留原始 JSON、实际截图或诊断报告。过去,这些文件要么污染项目目录,要么藏在难以寻找的临时目录中。Go 1.26 新增的 ArtifactDir,为测试产物提供了统一的存放方式。

ArtifactDir 解决了什么问题

Go 1.26 为普通测试、基准测试和模糊测试提供了 T.ArtifactDirB.ArtifactDirF.ArtifactDir

它们返回由测试框架管理的可写目录,适合保存截图、日志、响应数据和分析报告。

同一个测试重复调用 ArtifactDir 会得到相同目录,不同测试和子测试则各有独立目录。子测试目录不位于父测试目录之下,因此不要依赖父子路径关系查找文件。

需要注意,F.ArtifactDir 应在调用 F.Fuzz 前使用。进入模糊测试目标函数后,*testing.F 只允许调用 FailedName,此时应通过回调参数 *testing.Tt.ArtifactDir 获取产物目录。

保存接口的原始响应

接口测试可以把服务端响应保存为 JSON:

func TestUserAPI(t *testing.T) {
    body := requestUser(t)
    path := filepath.Join(t.ArtifactDir(), "response.json")
    if err := os.WriteFile(path, body, 0o644); err != nil {
        t.Fatal(err)
    }
    assertUser(t, body)
}

filepath.Join 可以正确处理不同系统的路径分隔符,写入失败也不应被忽略。

示例每次都会保存响应。如果产物较大,可以先比较结果,仅在失败时写入。此时断言函数不能立即调用 t.Fatal,而应先返回比较结果。

默认目录为什么找不到

直接运行 go test ./... 不需要增加参数。

此时 ArtifactDir 返回临时目录。测试执行期间可以正常读写,测试结束后目录会自动删除。

这种模式适合只在测试过程中使用的中间文件。如果需要在测试结束后查看截图或响应,就要启用保留模式。

使用 artifacts 保留文件

Go 1.26 为 go test 增加了 -artifacts 参数,执行命令为 go test -v -artifacts ./...

首次调用 ArtifactDir 时,测试日志会记录实际目录,例如 === ARTIFACTS TestUserAPI /path/to/artifact/dir。使用 -v 可以在测试通过时看到这条日志。

官方只保证产物位于输出目录之下,不承诺具体的子目录命名规则。脚本不应自行推算路径,而应以日志中 === ARTIFACTS 后面的路径为准。

需要指定输出位置时,可以配合 -outputdir

mkdir -p test-results
go test -artifacts -outputdir ./test-results ./...

-artifacts 决定是否保留产物,-outputdir 决定输出位置,也会影响性能分析文件的位置。Go 1.26.x 当前工具链要求指定的输出目录已经存在,因此命令执行前先用 mkdir -p 创建目录。

子测试和并行测试

在表驱动测试中,ArtifactDir 会为每个子测试分配独立目录:

for _, tc := range cases {
    t.Run(tc.name, func(t *testing.T) {
        t.Parallel()
        path := filepath.Join(t.ArtifactDir(), "result.json")
        saveResult(t, path, tc.input)
    })
}

即使多个子测试使用相同文件名,实际路径也互不相同。

不过,同一测试中的多个 Goroutine 仍需使用不同文件名或自行同步。ArtifactDir 只负责测试之间的目录隔离,不会协调目录内部的并发写入。

在 CI 中留下失败现场

ArtifactDir 可以与 CI 的归档能力配合:

- run: mkdir -p test-results
- run: go test -artifacts -outputdir ./test-results ./...
- uses: actions/upload-artifact@v4
  if: always()
  with:
    path: test-results

if: always() 可以确保测试失败后仍上传现场。测试产物适合保存响应、截图和诊断报告,但不能代替断言。

使用时还要注意:

  • 限制大文件体积和 CI 保留时间。
  • 对令牌、Cookie 和用户信息进行脱敏。
  • 不要在业务代码中依赖测试专用的 ArtifactDir
  • 项目需要使用 Go 1.26 或更高版本。

写在最后

ArtifactDir 解决的不只是如何写文件,还统一了测试产物的位置和生命周期。

默认模式会自动清理,启用 -artifacts 后则能保留失败现场。再配合 -outputdir 和 CI 归档,截图、响应与诊断报告都有了明确去处。