【OpenHarmony/HarmonyOS】游戏项目测试体系:用 Hypium 覆盖迷宫、碰撞、存储与页面流程
【OpenHarmony/HarmonyOS】游戏项目测试体系:用 Hypium 覆盖迷宫、碰撞、存储与页面流程
Canvas 游戏常被误认为“只能靠手玩测试”。实际上,迷宫、向量、碰撞、结算和存储都非常适合自动化。本文基于项目现状设计一套从纯函数单测到真机流程测试的分层方案。🧪
一、先正视当前测试现状
工程已经接入@ohos/hypium,本地测试和 ohosTest 目录也存在,但现有用例主要是模板断言:
it('assertContain',0, () => { const a = 'abc';const b = 'b';expect(a).assertContain(b);expect(a).assertEqual(a);});这只能验证测试框架能运行,不能保护项目的核心逻辑。高价值测试应该优先覆盖“容易被数值和边界改坏”的部分。
二、建立测试金字塔
少量:真机端到端流程 中量:组件、Preferences、Ability 集成测试 大量:Vector2、迷宫、A*、碰撞、经济规则纯单测游戏画面最终仍需要人工和截图检查,但底层规则越多被自动化覆盖,实机测试越能专注于手感、视觉和性能。
三、Vector2 是最适合起步的单元
向量是移动、距离和 AI 的基础。应测试:
it('normalize_zero_vector',0, () => { const result = new Vector2(0,0).normalize();expect(result.x).assertEqual(0);expect(result.y).assertEqual(0);});it('normalize_length_should_be_one',0, () => { const result = new Vector2(3,4).normalize();expect(Math.abs(result.length() -1) <0.0001) .assertTrue();});源码中的dot()当前返回一个Vector2(x1*x2, y1*y2),而标准点积应返回标量x1*x2 + y1*y2。一条契约测试就能暴露这类类型和数学语义错误。
四、随机迷宫怎样测试?
随机不等于不可测。可以先验证性质:
1. 尺寸与值域
数组非空、每行等长、所有格子值属于允许集合。
2. 边界
最外层墙是否完整,或至少不会产生地图外出生点。
3. 连通性
从起点对所有空地进行 BFS,关键出生区和出口必须可达。
4. 出生区域
左上和右下逻辑房间是否被清空,3 x 3范围能容纳坦克。
5. 压力生成
循环生成数百或数千次,断言不越界、不抛异常、耗时不超过合理范围。
最理想的方式是给MazeGenerator注入带种子的随机源,失败时打印 seed,就能完全复现地图。
五、A* 的表格驱动测试 🧭
准备几张小地图:
直线可达 中间有墙需要绕行 终点完全封闭 起点越界 终点越界 只有一格宽通道 包含砖墙和水面断言路径:
- 非空路径首尾正确;
- 每两个节点曼哈顿距离为 1;
- 不穿过类型 1、2、4;
- 无路时返回
null; - 路径长度等于预期最短距离;
- 大地图触发迭代上限时不阻塞。
六、碰撞逻辑需要从 private 中提取
Tank.checkCollision和Bullet.handleBounce是 private,难以直接测试。不要为了测试强行访问私有字段,建议抽出纯函数:
exportfunctioncollidesWithMaze(x:number, y:number, halfSize:number, cellSize:number, maze:number[][]):boolean;exportfunctionreflectAxisAligned(velocity: Vector2, hitX:boolean, hitY:boolean):Vector2;随后覆盖坦克跨过一格薄墙、贴边滑动、地图边界、砖墙、水面、墙角双反射和最大反弹次数。
七、固定时间步长测试
给 GameLoop 的时间来源也做依赖注入,模拟帧间隔:
- 8.33ms 应更新一次;
- 16.66ms 应更新两次;
- 小于一步时只渲染不更新;
- 300ms 应先被截断到 250ms;
- 超过最大补算步数时应清空累加器;
- 重复
start()不创建第二循环; stop()后不再回调。
不要在单元测试里真的等待几百毫秒,虚拟时间能让用例稳定而快速。
八、经济系统的契约测试 💎
UpgradeManager 应重点验证:
- 金币不足不扣款、不升级;
- 刚好足够时成功;
- 满级时价格和购买结果一致;
- 速度、射速、护盾价格分别符合统一配置;
- 购买后只增加目标等级;
- 保存失败时内存状态如何处理;
- 同时发起两次购买不会出现负金币。
这类测试会直接发现当前页面护盾价格与 Manager 实际扣费不一致的问题。
九、Preferences 集成测试
使用测试 Context 或可替换存储接口,覆盖:
- 空存储返回默认值;
- 用户 JSON 正常读取;
- 损坏 JSON 不导致页面崩溃;
- 排行榜按分数降序;
- 超过 100 条被截断;
- PvE/PvP 键互不影响;
- 重启 Manager 后状态仍存在;
- 旧 schema 能迁移到新 schema。
为了便于测试,Manager 可以依赖KeyValueStore接口,正式实现包装 Preferences,测试实现使用内存 Map。
十、组件与页面测试
VirtualJoystick
- Down 时底座移动到触点;
- Move 超过最大半径时输出长度仍为 1;
- Up/Cancel 输出零向量;
- 视觉层不拦截事件。
LeaderboardPage
- 加载中、空数据、有数据三种状态;
- 前三名样式;
- 本地资源头像、网络头像、默认头像。
StartPage
- 未同意时不进入主页;
- 已有本地用户时正确显示欢迎;
- WebView 路由失败时回退本地弹窗。
十一、真机流程和系统能力测试 📱
以下内容不能只靠本地纯单测:
- SoundPool 首次播放延迟与并发;
- AVPlayer 前后台恢复;
- 振动权限和不同设备效果;
- 折叠屏状态变化;
- WebView 网络失败与返回;
- UDP 广播在真实路由器环境中的可达性;
- Canvas 触摸双指操作;
- 60/90/120Hz 设备上的帧稳定性。
真机测试要记录设备型号、系统版本、刷新率和网络拓扑,便于复现。
十二、性能回归测试
创建固定 seed 的压力场景:
40 个 AI 每辆坦克 5~10 颗子弹 300 个粒子 最大波次地图 小地图开启 网络状态 20Hz记录 60 秒内平均 FPS、P95/P99 帧时间、内存增长和对象池命中率。每次优化或新增特效后比较基线,防止“功能正常但帧率慢慢下降”。
十三、CI 中的最低门槛
- ArkTS 编译通过;
- 纯单测全部通过;
- 资源 JSON 格式和多语言键完整;
- 禁止提交密钥、Token 和证书密码;
- Release 混淆构建可完成;
- 核心模块覆盖率达到团队设定标准;
- 固定 seed 的迷宫性质测试全部通过。
十四、总结 ✨
Canvas 游戏完全可以建立可靠的自动化测试:
- 纯数学、迷宫、A* 和经济规则做大量单测;
- 存储和组件做集成测试;
- 音频、振动、折叠和网络留给设备测试;
- 随机算法使用 seed 复现;
- 私有复杂逻辑抽成纯函数;
- 固定压力场景建立性能基线;
- 模板测试必须尽快替换为真实业务用例。
自动化不能替代“手感测试”,但它能让开发者不必每次手玩十分钟,才发现一颗子弹穿墙或一次购买扣错了金币。✅
推荐标签:HarmonyOSOpenHarmonyHypium单元测试游戏测试ArkTS
