MetricKit 的诊断载荷不会按提交节奏到达。解析器今天改了一行,真正的崩溃或卡顿报告可能几天后才暴露字段丢失。更稳妥的做法,是把已取得的载荷脱敏、归一化并保存为固定样本,让云端 Mac 上的每次提交都重放同一批输入。这样验证的是诊断链路本身,而不是等待下一次偶发事件。
先划清测试边界
固定样本适合覆盖四层逻辑:原始 JSON 能否读取、系统字段能否映射到内部模型、敏感内容是否被清除、异常输入能否降级。它不能证明系统一定会产生载荷,也不能替代设备侧回调验证。
建议把接收代码与业务处理拆开。接收层只负责取得 jsonRepresentation()、写入受保护目录并排队上传;解析层接收 Data,输出不依赖 MetricKit 类型的内部结构。单元测试只调用后者,避免测试目标必须伪造系统对象。
样本的价值不是模仿一次成功解析,而是固定输入契约,让每次解析器修改都能回答“哪些字段变了,哪些信息被丢弃”。
建立可入库的归一化样本
原始载荷可能包含包标识、设备信息、时间、调用栈符号和本机路径。不要直接提交。先在受限环境保留原件,再生成可进入仓库的归一化副本:时间改成固定值,标识符改为测试值,路径替换为 $APP、$HOME,调用栈地址保留格式但不保留真实地址。
可以为内部格式增加 schema,但不要改写原始 MetricKit 版本。目录按诊断类型组织:
Tests/Fixtures/MetricKit/
├── crash/basic.json
├── crash/missing-stack.json
├── hang/main-thread.json
├── disk-write/threshold.json
└── malformed/truncated.json
每个样本只表达一个条件。若一个文件同时包含崩溃、卡顿和磁盘异常,失败后很难定位。样本名称描述输入,不描述预期结果;预期值放在测试代码里,评审时更容易发现断言被顺手改掉。
先做结构门禁再运行测试
在编译测试前用 jq 做廉价检查,可以快速拦住无效 JSON、遗漏版本和未脱敏路径。下面的 diagnostics 是团队自己的归一化数组,不是假定系统原始载荷具有同样结构。
set -euo pipefail
root="Tests/Fixtures/MetricKit"
find "$root" -name '*.json' -print0 |
while IFS= read -r -d '' file; do
jq -e '
type == "object" and
.schema == 1 and
(.diagnostics | type == "array") and
all(.diagnostics[];
(.kind | type == "string") and
(.timestamp | type == "string") and
(.stackID | type == "string")
)
' "$file" >/dev/null
if grep -E '/Users/|/private/var/|[A-F0-9]{16,}' "$file"; then
echo "fixture contains unnormalized data: $file" >&2
exit 1
fi
done
结构门禁不应规定所有系统字段,否则新增可选字段会制造无意义失败。只检查内部处理真正依赖的键,并让解码器忽略未知字段。
用正反样本覆盖解析契约
至少准备一组正常输入和三组失败输入。测试重点不是“没有抛错”,而是输出是否仍可用于聚合、告警与排查。
| 样本 | 预期行为 | 不应发生 |
|---|---|---|
| 完整崩溃 | 输出类型、时间和栈标识 | 保存原始本机路径 |
| 空诊断数组 | 返回空结果 | 当作解码失败 |
| 缺少调用栈 | 标记为不完整 | 伪造空栈为正常数据 |
| 截断 JSON | 返回可分类错误 | 进程直接退出 |
| 未知类型 | 记录未知枚举 | 丢弃整批载荷 |
断言内部模型而非整段 JSON
整段快照很容易被字段顺序和无关元数据扰动。优先断言诊断数量、类型、稳定标识和脱敏结果;只有归一化输出用于跨系统交换时,才增加格式化 JSON 快照。错误也应成为可比较的枚举,例如 invalidJSON、missingRequiredField、unsupportedDiagnostic,不要只比较易变的自然语言消息。
接入云端 Mac CI
在 VMRunner 的云端 Mac 上,把 fixture 检查放在单元测试之前,并确保非交互式任务使用固定工作目录。一个可执行顺序是:检出代码、运行结构门禁、执行解析器单测、生成测试结果、最后检查工作区是否出现未提交的样本变化。
样本变化必须单独评审。新增系统字段时,先确认解析器是否需要消费;需要时升级内部 schema 并同时提交迁移测试,不需要时保持宽松解码。不要用脚本在 CI 中自动覆盖基准文件,否则真正的字段丢失会被新的错误结果“批准”。
合并前检查项
- 原始载荷已在仓库外完成脱敏。
- 每个样本只覆盖一个诊断条件。
- 正常、空值、缺字段、截断和未知类型均有测试。
- 未知可选字段不会导致整批失败。
- 本机路径、长标识符和用户内容无法通过门禁。
- 解析失败会返回稳定错误类别。
- fixture 变化与解析器变化由同一评审确认。
完成这些约束后,MetricKit 诊断处理就从“收到数据后再试”变成了普通、可重复的工程测试。系统载荷仍需设备侧验证,但解析、脱敏和兼容性不再依赖偶然到达的报告。
常见问题
MetricKit 固定样本可以完全替代真机验证吗?
不能。固定样本适合验证解析、脱敏、映射和异常降级逻辑;系统是否按预期产生并回调诊断载荷,仍应通过受控设备测试和线上观测确认。
样本是否应该直接保存原始 MetricKit JSON?
建议同时保留受限访问的脱敏原始样本和可进入仓库的归一化样本。回归测试优先读取归一化版本,原始版本仅用于排查字段兼容问题。
系统增加未知字段时,CI 应该立即失败吗?
通常不应因未知字段失败。解码器应忽略可选新增字段,但缺少内部契约要求的诊断类型、时间、调用栈标识等关键字段时必须失败。
把下一次构建放到独享云端 Mac 上运行
选择机型、节点与计费周期。配置和美元金额在下单前完整列明,可用状态以控制台实时返回为准。