用状态机做移动游戏端到端稳定性自动化
在移动游戏项目里,端到端自动化最容易失败的原因,通常不是“不会点按钮”,而是“点得太早、状态还没稳定、分支判断误判”。这篇文章分享一套可落地的方法:用状态机组织流程,用条件等待替代盲等,用统一日志做可观测,最终在真机上稳定跑完完整业务链路。
一、目标与边界
目标不是做像素级 UI 回放,而是覆盖一条真实业务闭环:
- 登录
- 判断业务状态(例如某功能是否开启)
- 开启则执行 A 分支,否则执行 B 分支
- 执行完成后继续公共流程
- 最终回到可验证的收尾状态(如退出登录)
边界是:
- 依赖项目已有业务 API(推荐)
- 不依赖录制点击坐标(脆弱)
- 优先验证“流程可达 + 关键动作成功”
二、核心架构:触发层与执行层分离
建议分两层:
- 触发层
- 负责“启动一次测试”
- 可以是编辑器命令、GM 指令、调试按钮、启动参数
- 执行层
- 负责完整业务流程
- 包含状态机、等待、超时、容错、日志
这样做的好处:
- 真机和编辑器共享同一份流程逻辑
- 触发方式可替换,核心测试不变
- 后续接 CI 更容易
三、状态机设计(最关键)
把流程拆成有限状态,避免“线性脚本越写越乱”:
- Login
- CheckCondition
- BranchA(例如执行关键消费动作)
- BranchB(例如聊天动作)
- CommonTail(公共后续流程)
- Logout
- Done/Failed
原则:
- 一个状态只做一件事
- 每个状态必须有成功出口和超时出口
- 失败也要有收尾路径(尽量回到登录态)
四、等待策略:固定等待 + 条件等待混合
仅用 sleep 会脆,完全不用 sleep 也会抢跑。实战里建议混合:
- 固定等待(节流)
- 用于重页面切换、资源加载、动画过场
- 例如每步间隔 10~20 秒(按项目调参)
- 条件等待(轮询直到成立)
- 例如“当前模式是否进入主界面”“是否收到回复”
- 必须设置超时,防止死等
一个通用思路:
- wait_until(predicate, timeout, interval)
- 条件成立 -> 继续
- 超时 -> 记录失败原因并走降级路径
五、幂等与防重入
自动化常见问题是“误触发两次”导致流程互相干扰。
解决方法很简单:
- 全局 running 标记
- 运行中再次触发直接返回
- 结束时统一释放标记
这一步对真机长测特别重要。
六、分支流程的实战策略
以“状态判断后分支”举例:
- 若条件为真:先做关键动作(如消费、互动),等待短缓冲(如 5 秒),再进入公共分支
- 若条件为假:直接走公共分支
关键点:
- 分支动作成功判定尽量看“响应结果 + 业务状态变化”
- 不要只靠“函数调用没报错”当成功
七、可观测性:日志前缀统一 + 结构化结果
建议所有日志统一前缀,例如:
- [STABILITY_TEST] step=...
- [STABILITY_TEST] result=pass/fail reason=...
同时输出结构化结果(JSON 或 key-value):
- 用例名
- 开始/结束时间
- 失败步骤
- 错误码/超时原因
这样后续接日志平台、CI 报表会非常顺滑。
八、真机落地方案
真机上通常不方便直接跑编辑器脚本,因此推荐:
- 在运行时提供触发入口
- GM 指令
- 隐藏调试菜单
- 启动参数自动触发
-
执行层在运行时环境内完成全流程
-
日志回收
- Android: logcat
- iOS: 设备日志
- 云真机:平台日志接口
九、跨引擎复用(UE / Unity)
这套方法是引擎无关的,可复用的是“框架思想”:
- 状态机编排
- 固定等待 + 条件等待
- 幂等防重入
- 统一日志与结果上报
- 失败后收尾恢复
不同引擎只替换“实现细节”:
- 定时器/协程机制
- 页面与业务 API
- 事件总线与网络回包监听
十、最小伪代码
if running: return running = truegoto Login wait_until(MainReady, timeout)sleep(step_gap) if FeatureEnabled():do CriticalAction()wait_response_or_timeout()sleep(post_action_gap)do CommonAction() wait_until(CommonDone, timeout)do Logout() wait_until(BackToLogin, timeout)running = false
十一、常见坑与调参建议
- 误判“功能未开启”
- 常见原因:页面刚切完就判断
- 解决:增加状态判断前缓冲
- 关键动作“调用了但没生效”
- 常见原因:只看本地调用,不看服务端响应
- 解决:记录响应码/业务事件
- 流程卡死
- 常见原因:缺超时
- 解决:每个等待都必须有 timeout
- 不同机型稳定性差异大
- 解决:把时间参数集中配置化(如 step_gap、reply_timeout)
十二、结语
稳定性自动化的重点不是“模拟用户点击”,而是“可控地驱动业务状态变化并验证结果”。
当你把流程状态化、等待可控化、日志结构化后,这套方案就能从本地调试平滑迁移到真机回归,甚至扩展到夜间持续测试。
