Go test -json 怎样把测试事件导出给日志系统
来源:17golang原创
时间:2026-10-28 22:44:35 152浏览 收藏
在项目根目录执行 go test -json ./...,把 stdout 保存成 NDJSON 文件,再让日志采集器按“一行一个 JSON 对象”读取,就能导出 Go 测试事件。实际接入时还应单独保存 stderr,并保留 go test 的退出码,否则日志上传成功可能掩盖测试失败。
官方地址:https://pkg.go.dev/cmd/go
# 在当前模块导出事件;stderr 单独存放,避免污染 JSON 文件。 go test -json -count=1 ./... > test-events.ndjson 2> test-command.stderr
这条命令适合手动开始;在 CI 中需要下面的完整退出码处理。本文把接入方式从“解析人类文本”调整为“消费结构化事件”,借用提案解读的方式说明改动理由和兼容成本,不将现有参数说成刚发布的新能力。
为什么应替换按 PASS 文本搜索的旧采集方式
普通测试输出方便人读,但用 grep PASS 决定成败,会把测试打印的文字、单个测试结果和整个包的结果混在一起。多包同时测试时,按屏幕位置猜测消息属于哪个测试也不可靠。
事件采集应保留两个层次:进程退出码决定本次命令结果,结构化事件用于检索与解释。日志系统负责索引,不应成为另一套用字符串猜测结果的测试框架。建议把原始 NDJSON 当作可重放的输入,在额外字段中加入 CI 运行信息,而不是修改 Go 自带字段的含义。
新接入规则:一行一条,先看 Action 再解释字段
官方 test2json 文档定义了逐行测试事件。Action 描述事件类别,例如 run、output、pass、fail。Package 标识测试包,Test 可标识具体测试;包级事件没有 Test。采集器应根据实际事件是否包含字段解释它,不能要求所有记录都有测试名和耗时。
当前 Go 命令文档还规定构建事件会混入此流,以 build-output、build-fail 区分,构建包标识使用 ImportPath。它不是 TestEvent.Package 的简单替代。处理构建失败时应保留这一标识,避免把失败依赖错误地归到某个测试函数。
| 检索用途 | 保留字段或外加字段 | 接入规则 |
|---|---|---|
| 本次 CI 执行 | run_id | 由 CI 提供,区别不同运行 |
| 事件类别 | Action | 保留原值,未知值也保留原事件 |
| 测试归属 | Package、Test | 缺少 Test 时不要随意补前一个测试名 |
| 构建归属 | ImportPath | 保留为独立字段 |
| 可读消息 | Output | 保留字符串,不用其内容推断成败 |
| 命令诊断 | 独立 stderr 文件、退出码 | 作为同次运行的另一类记录归档 |

代码对比:导出日志后仍让 CI 收到失败
下面是可保存为 collect-tests.sh 的 Bash 示例。调用时给它一个本次运行专用的输出目录,例如 bash collect-tests.sh artifacts/job-472-attempt-1。路径只是示例,应由 CI 生成唯一目录,避免并发任务互相覆盖。
#!/usr/bin/env bash
# 输出目录由 CI 分配;每次运行使用独立目录。
set -u
set -o pipefail
out_dir="${1:?请提供本次运行的独立输出目录}"
mkdir -p "$out_dir" || exit 2
# 记录工具链版本;记录失败时停止,不伪装采集成功。
go version > "$out_dir/go-version.txt" 2>&1 || exit 2
# if 分支允许获取真实退出码,不受调用环境的 errexit 干扰。
if go test -json -count=1 ./... \
> "$out_dir/events.ndjson" 2> "$out_dir/command.stderr"; then
test_rc=0
else
test_rc=$?
fi
# 单独保存命令结果;没有 JSON 事件时也有可诊断的记录。
printf '%s\n' "$test_rc" > "$out_dir/test-exit-code.txt" || exit 2
# 由 CI 的始终执行步骤归档上述文件,然后使用这里的状态判定测试结果。
exit "$test_rc"
与把命令直接管道接到上传器相比,这个版本先落盘,明确保留命令状态。它没有调用任何真实日志服务,也没有隐含“导出即上传”的行为。CI 需要把归档或日志采集设置为失败后仍执行;如果测试失败便取消后续所有步骤,文件虽然存在,也不会自动进入日志系统。
不要把 2>&1 放到事件文件的采集命令中。官方文档提示,某些早期严重错误仍可能以非 JSON 文字写到命令 stderr。测试自身的输出又可能作为事件的 Output 存在,两者不能据“都是错误文字”合并解析。
给日志系统添加信封,而不覆盖原始事件
如果现有采集器能直接解析 NDJSON,可配置外加运行字段后采集原文件。需要预处理时,下面的 jq 示例生成独立文件,要求已安装 jq;CI_RUN_ID 由 CI 注入,不是 Go 事件自带字段。
# 为每条事件外包运行标识,原始对象完整留在 event 字段。
# out_dir 指向刚才采集目录;以下转换与上传需在失败后仍执行的 CI 步骤中运行。
out_dir="artifacts/job-472-attempt-1"
jq -c --arg run_id "${CI_RUN_ID:?请设置本次运行标识}" \
'{source:"go-test", run_id:$run_id, event:.}' \
"$out_dir/events.ndjson" > "$out_dir/log-events.ndjson"
这里没有使用 -s,不会先把整份文件聚合成一个 JSON 数组。日志系统按每行解码后,可将 event.Action 建成类别字段;查询具体测试时组合 run_id、event.Package 和 event.Test。同一测试在一次执行中重复运行时,这组字段只适合检索归组,不能直接充当事件唯一键。
若要进行重试去重,可由采集侧保存文件身份与原始记录序号,具体索引方案由日志系统决定。不要拿采集时间覆盖事件时间,也不要因为某条记录缺少时间就丢弃它。stderr、命令退出码和事件索引都应带相同 run_id,以便回到同一次 CI 执行。

兼容注意:并行、缓存与新增事件
多包与并行测试的事件可能交错,接入器不能把整个文件当成单个测试连续文本。若需要还原可读输出,应按所需范围保留 Output 片段顺序,而不是按字母重新排序。JSON 字符串中的转义换行不应被采集器当成新的外层记录切开。
示例用 -count=1 避免使用缓存的成功测试结果;它不等于禁用构建缓存,也不等于覆盖了所有测试场景。若保留缓存行为,需要接受缓存记录可能省略时间这一情况,另存采集时间时明确其不同含义。
不同工具链的字段和构建诊断形式可能变化。接入解析应容忍额外字段与未知 Action,归档实际 Go 版本;碰到不能解析的原始记录应单独记录采集错误并保存原文,不能静默跳过后宣布完整导出。命令退出码非零时,检查 stderr 和构建事件,即使没有任何具体测试 fail 事件也不能算测试通过。
还需要再管道到 go tool test2json 吗?
正常使用 go test -json 时不需要重复转换。官方建议优先使用这一入口;单独运行测试二进制时才考虑 test2json 的独立用法。
能只统计所有 fail 事件得到失败测试数吗?
不能直接这样统计。包级失败与具体测试失败作用域不同,构建失败也需分开,先定义统计对象再聚合。
日志平台收到了数据,CI 就可以返回成功吗?
不可以。上传是否成功和测试是否成功是两项结果。保留测试原退出码;上传失败则另外报告采集问题。建议先采用原始文件归档,再增量加入字段索引和可视化。
-
502 收藏
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
293 收藏
-
151 收藏
-
144 收藏
-
242 收藏
-
138 收藏
-
301 收藏
-
127 收藏
-
166 收藏
-
381 收藏
-
162 收藏
-
351 收藏
-
292 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习