当前位置:首页 > 文章列表 > Golang > Go问答 > Go test -json 怎样把测试事件导出给日志系统

Go test -json 怎样把测试事件导出给日志系统

来源:17golang原创 2026-10-28 22:44:35 0浏览 收藏

在项目根目录执行 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 执行。

测试采集目录与日志归档责任之间的静态关系
结构说明图:事件文件、命令 stderr 和退出码文件属于同次运行;CI 始终执行步骤负责归档,日志系统可通过 run_id 关联这些对象。

兼容注意:并行、缓存与新增事件

多包与并行测试的事件可能交错,接入器不能把整个文件当成单个测试连续文本。若需要还原可读输出,应按所需范围保留 Output 片段顺序,而不是按字母重新排序。JSON 字符串中的转义换行不应被采集器当成新的外层记录切开。

示例用 -count=1 避免使用缓存的成功测试结果;它不等于禁用构建缓存,也不等于覆盖了所有测试场景。若保留缓存行为,需要接受缓存记录可能省略时间这一情况,另存采集时间时明确其不同含义。

不同工具链的字段和构建诊断形式可能变化。接入解析应容忍额外字段与未知 Action,归档实际 Go 版本;碰到不能解析的原始记录应单独记录采集错误并保存原文,不能静默跳过后宣布完整导出。命令退出码非零时,检查 stderr 和构建事件,即使没有任何具体测试 fail 事件也不能算测试通过。

还需要再管道到 go tool test2json 吗?

正常使用 go test -json 时不需要重复转换。官方建议优先使用这一入口;单独运行测试二进制时才考虑 test2json 的独立用法。

能只统计所有 fail 事件得到失败测试数吗?

不能直接这样统计。包级失败与具体测试失败作用域不同,构建失败也需分开,先定义统计对象再聚合。

日志平台收到了数据,CI 就可以返回成功吗?

不可以。上传是否成功和测试是否成功是两项结果。保留测试原退出码;上传失败则另外报告采集问题。建议先采用原始文件归档,再增量加入字段索引和可视化。

参考:Go test 参数与构建事件格式、test2json 事件格式。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go pprof 标签没有出现在 profile 中怎么办Go pprof 标签没有出现在 profile 中怎么办
上一篇
Go pprof 标签没有出现在 profile 中怎么办
Go fuzz 测试如何保存和复现崩溃输入
下一篇
Go fuzz 测试如何保存和复现崩溃输入
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    761次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    758次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    842次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    810次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    640次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码