为 MetricKit 诊断数据建立固定样本回归测试

为 MetricKit 诊断数据建立固定样本回归测试

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 快照。错误也应成为可比较的枚举,例如 invalidJSONmissingRequiredFieldunsupportedDiagnostic,不要只比较易变的自然语言消息。

接入云端 Mac CI

在 VMRunner 的云端 Mac 上,把 fixture 检查放在单元测试之前,并确保非交互式任务使用固定工作目录。一个可执行顺序是:检出代码、运行结构门禁、执行解析器单测、生成测试结果、最后检查工作区是否出现未提交的样本变化。

样本变化必须单独评审。新增系统字段时,先确认解析器是否需要消费;需要时升级内部 schema 并同时提交迁移测试,不需要时保持宽松解码。不要用脚本在 CI 中自动覆盖基准文件,否则真正的字段丢失会被新的错误结果“批准”。

合并前检查项

完成这些约束后,MetricKit 诊断处理就从“收到数据后再试”变成了普通、可重复的工程测试。系统载荷仍需设备侧验证,但解析、脱敏和兼容性不再依赖偶然到达的报告。

常见问题

MetricKit 固定样本可以完全替代真机验证吗?

不能。固定样本适合验证解析、脱敏、映射和异常降级逻辑;系统是否按预期产生并回调诊断载荷,仍应通过受控设备测试和线上观测确认。

样本是否应该直接保存原始 MetricKit JSON?

建议同时保留受限访问的脱敏原始样本和可进入仓库的归一化样本。回归测试优先读取归一化版本,原始版本仅用于排查字段兼容问题。

系统增加未知字段时,CI 应该立即失败吗?

通常不应因未知字段失败。解码器应忽略可选新增字段,但缺少内部契约要求的诊断类型、时间、调用栈标识等关键字段时必须失败。

独享物理节点

把下一次构建放到独享云端 Mac 上运行

选择机型、节点与计费周期。配置和美元金额在下单前完整列明,可用状态以控制台实时返回为准。

选择方案并下单