测试与排障
本页把“编译通过”与“用户在真机上真的能顺畅使用”分开。对于 VoxelViewer,后者更重要:Component3D 的首帧、材质资源、手势竞争和 Picker URI 生命周期不能只靠静态编译证明。
验证层次
| 层次 | 验证内容 | 不能替代 |
|---|---|---|
| 静态检查 | ArkTS 编译、公开类型、资源路径。 | Scene 可见性、手势和性能。 |
| HAR 构建 | 产物可生成,README/License 打包正确。 | 独立宿主兼容性。 |
| Demo 构建 | entry 能消费 HAR API。 | 真机 Component3D 行为。 |
| 真机手动验证 | 首帧、背景、光照、动画、双指手势、Picker。 | 资产权威验证。 |
| VFP Reader 验证 | 容器/目录/CRC。 | VOX0/source hash 验证。 |
一次完整的验收顺序
- 构建:确认 HAR 与消费它的宿主工程都能编译。
- 挂载:真机打开预览页,空状态、背景和 Viewer 尺寸正确。
- 输入:分别导入小 JSON、典型 128³ JSON、VFP 1.2、VFP 1.3。
- 交互:单指旋转;双指平移、缩放、手指取消和结束;动画结束后立即重复操作。
- 视觉:浅/深背景、彩色/纯黑模型、网格开关、单位描边首帧和载入动画。
- 切换:连续导入两份不同模型、页面离开再进入,确保旧场景/描边不晚到。
- 失败:取消 Picker、空文件、超限文件、损坏 VFP、无 PRVW 的 VFP。
把第 2–6 步保留为目标设备的视频/截图或人工检查记录;性能问题和视觉问题需要这种证据才能复现。
推荐回归清单
Preview
- JSON 小模型:可见、颜色正确、单指旋转,双指平移/缩放正确。
- 典型 128³ JSON:不出现 AGP 残影,动画结束立即可操作。
- VFP 1.3:URI 路径无
bad file descriptor,PMSH 缓存命中时可见。 - 深浅背景:模型显色和网格可辨,不产生全局发灰或全黑。
- 有/无
unitGridTexture:前者首帧 PBR 描边,后者仅验证回退可用。 - 页面离开/重进:旧动画或边线不会附着到新 Scene。
Reader
- 破坏 Header、Footer、DIR0、一个区段 CRC:
validate()都应拒绝。 - 没有
PRVW:查询为undefined,不影响 parse/validate。 - 非 GLB 2.0
PRVW:extractPreviewGlb()拒绝。 - 大于 64 MiB URI:Reader 与 Viewer 都应拒绝。
外置 UI 回归
backgroundMode = BUILTIN、BUILTIN_CUSTOM、BUILDER、EXTERNAL四种模式均不遮挡 3D 内容。loadOverlayMode = BUILTIN、BUILTIN_CUSTOM、BUILDER、EXTERNAL均能经历 IDLE、导入、准备、动画、错误、隐藏。EXTERNAL模式下不应再出现 HAR 自带遮罩;宿主 Overlay 用state.visible驱动,错误后可显示state.errorMessage。BUILDER模式下 Builder 只替换卡片,仍由 HAR 管理遮罩可见性。
常见现象
| 症状 | 可能根因 | 检查与处理 |
|---|---|---|
| 导入提示成功但画面空白 | Component3D Surface 尚未挂载,或页面生命周期又加载了内置模型。 | 真机日志检查 Scene 代际和 aboutToAppear 逻辑。 |
bad file descriptor | URI 在异步读取完成前被调用方关闭/失效。 | 只传 loadUri() 或 Reader URI API;不要延后自行读取。 |
| 黑色模型描边太明显 | 走了旧 BORD 或调参曝光/环境光异常。 | 先确认 PBR 网格纹理可用,再从默认 Tuning 回归。 |
| 描边晚出现 | unitGridTexture 没有首载前设置。 | 使用宿主 $rawfile('voxel/voxel_grid.png')。 |
| VFP 预览与 JSON 光照不一致 | VFP 面方向适配或使用了不同 Render Tuning。 | 核对同一 Controller Tuning 和 Z-up → Y-up 归一化。 |
| 双指结束跳动 | 外层手势与 Viewer 同时更新相机。 | 删除竞争手势,保留 Viewer 的合并更新。 |
grid_size 错误 | JSON 缺字段、非整数、超 128 或 data 长度不对。 | 校验输入合同。 |
validate() 成功但不能标记为“可编辑” | 将容器 CRC 完整性误当成权威语义校验。 | 使用完整格式工具恢复 VOX0/PAL0 并重算 source hash。 |
extractPreviewGlb() 报错 | 文件没有 PRVW,或 PRVW 不是合法 GLB 2.0。 | 先 findSection('PRVW');它是可选缓存,不是正式 GLB 导出。 |
| 自定义遮罩永远不隐藏 | 宿主把 message 当作状态枚举,或未根据 visible 更新。 | 用 state.visible 控制展示,用 phase 区分样式。 |
日志与错误记录
宿主建议记录:业务任务 ID、源名称、文件大小、输入类型、VoxelLoadResult、getLastError() 和 HAR 版本。不要把完整 URI、私有文件内容或用户资产原文直接写入持久日志。
调试命令:
./scripts/logs.sh --device <device-serial> --from 5m --tail 300
对于渲染视觉问题,构建成功和日志无报错都不是完成证据;必须在目标设备录屏或手动验收。
最小诊断信息
出现问题时建议一次性记录以下非敏感字段,便于定位而不泄露用户资产:
VoxelKit 版本
设备型号 / 系统版本
输入类型(JSON / VFP)与文件大小
调用入口(loadText / loadBytes / loadUri)
VoxelLoadResult(若成功)
Controller 状态、lastError
是否设置 unitGridTexture
背景/Overlay 模式与是否播放动画
复现动作与真机截图或短录屏
不要把完整 Picker URI、JSON 原文、VFP payload 或用户模型截图写入长期日志。它们属于用户资产或可能包含隐私路径。
需要升级而非绕过的问题
- 需要程序化相机、自动旋转、体素编辑或 VFP 写回:不要访问内部 Scene,等待/设计独立公开能力。
- 文件超过 64 MiB:不要修改 Reader 私有常量或绕过 URI 生命周期,使用服务端预处理、分发策略或未来流式能力。
- 要验证 source hash/权威 VOX0:不要从 Viewer 的预览缓存反推,使用完整格式工具链。