UE5 + UnLua 自动化测试实践(一):从 Gauntlet 打通到游戏内 Lua 驱动的验收流程

UE5 + UnLua 自动化测试实践(一):从 Gauntlet 打通到游戏内 Lua 驱动的验收流程

系列:UE5 + UnLua 自动化测试实践 | 共 3 篇
本篇:(一)从 Gauntlet 打通到游戏内 Lua 驱动的验收流程
上一篇:— | 下一篇(二)Android 真机执行、报告回传与性能/闪退采集

说明:个人实践记录,面向 UE 开发者。文中业务细节、域名、地址、机型均已泛化;示意图为构造内容,非真实运行结果。

TL;DR

  • 做了什么:在一个以 Lua 承载业务逻辑(几十个独立业务模块)、强依赖网络(WebSocket / HTTP)的 UE 5.x 项目里,从零搭起四层自动化——引擎冒烟 → 纯逻辑单测 → 流程用例 → 游戏内真实操作链。
  • 核心取舍:主动放弃 SkipPIE 这类「快路」,让用例跑在真实游戏会话里、走玩家同一条操作链。宁可牺牲隔离性,也要保住验收有效性。
  • 最值钱的三个坑:UE 5.7 的 Gauntlet 命令已改名 RunUnrealUButton 没有 SimulateClick 接口,正确做法是广播 Slate 点击委托;UnLua 暴露的 TArray 不能用 # 取长度。
  • 适合谁读:正在或准备用 UE + UnLua 做自动化验收的开发者。

1. 背景:我们要的不是「看起来在跑」

在一个以 Lua 承载大量业务逻辑(几十个独立业务模块)、强依赖网络(WebSocket / HTTP)的 UE 5.x 项目中,手工验收的痛点很明显:功能点散、回归频繁、每轮发版都要人工点一遍关键路径。

我们想要的不是「看起来在跑」的假自动化,而是验收有效的自动化:

跑一遍能证明「这条玩家路径真的通」,而不是只证明「某个函数返回了 true」。

于是定下四层结构,从下往上依次加码:

四层自动化结构:耗时量级与运行频率

测什么 耗时量级 跑的频率
① 引擎冒烟 引擎能启、脚本运行时可用、数据模型能加载 毫秒级 每次都跑
② 纯逻辑单测 Lua 状态机、工具函数、数据解析 毫秒级 回归主力,每次跑
③ 流程用例 一条业务链路的步骤编排 秒级 每次跑
④ 游戏内真实操作链 玩家真实点击路径 分钟级 按需 / CI

这个分层本身就回答了一个常见困惑:自动化跑得慢不慢,取决于你把什么放在哪一层


2. 第一层:把 Gauntlet 跑起来

Gauntlet 是 UE 的端到端测试编排器。UE 5.7 有几个容易被忽略的变化,第一次接的时候基本都会卡在这里。

命令名变了。 现在是 RunUnreal 而不是 Gauntlet,用老命令会直接报 Failed to find command Gauntlet

跑编辑器内自动化测试用节点 UE.EditorAutomation,测试过滤走 -RunTest="过滤词"

-Build=Editor 必填,否则直接抛 No build specified

源码引擎默认会先重编 UAT,本机在 MSBuild 的 GetFileHash 任务上崩过。加 -nocompileuat 直接使用预编译的 AutomationTool.dll 规避。

无头参数-NullRHI -Unattended 即可:-Unattended 会自动追加 Automation RunTest <过滤>; Quit; 并在跑完后退出编辑器,非常干净。

日志和报告-LogDir / -TempDir / -ReportExportPath 重定向到工作区。Gauntlet 退出码 0 = 全部通过,CI 直接取用。

小坑:在编辑器控制台手动敲 Automation RunTest "xxx"不要带引号,带引号会导致过滤参数匹配不到任何用例。


3. 第二层:冒烟测试,让「启动即检」成为习惯

这一层只做三件事:引擎能启动、脚本运行时可用、所有业务数据模型能加载。

IMPLEMENT_SIMPLE_AUTOMATION_TEST 写毫秒级用例,跑在整条链路最前面。任何环境问题(缺模块、配置错误、脚本加载失败)都会第一时间暴露,而不是等到流程用例跑了一半才发现。


4. 第三层:给 Lua 写一个极简的契约式单测框架

业务逻辑都在 Lua,但项目没有现成的 Lua 测试框架(UnLua 自带的套件默认未启用)。我们写了一个极简 runner,契约只有两条:

-- 每个测试文件返回
return {
    Name = "模块名",
    Cases = {
        { Name = "用例描述", Fn = function() assert(...) end },
    },
}
  • runner 扫描测试目录下所有 .lua,逐文件 pcall,按行输出 ok / 失败 + 用例名 + 错误信息
  • 没有 Cases 的文件视为普通模块,直接跳过;
  • 只测纯逻辑:状态机、工具函数、数据解析——不碰 UI、不碰网络,所以跑得飞快,适合当回归主力。

Lua 侧的三个坑

现象 解法
模块名带了目录前缀 Script. 段被带进模块名,require 找不到 模块名与磁盘路径对齐,去掉 Script.
多行错误文本 破坏了「按行解析」的日志格式 先把 \n 折叠成空格再输出
TArray 不能用 # UnLua 把 UE 的 TArray 暴露成 userdata,没有 __len 元方法,#t 拿不到长度 :Num() 取长度,取元素用 1 基下标 t[i]

最后那条在流程自动化里几乎必踩,而且报错信息不明显,很容易查半天。


5. 第四层:从 Latent PIE 到游戏内驱动

初版流程用例用的是 Latent Automation Test + PIE:起一个 Play In Editor 世界,跑「进直播间 → 停留 → 退出」。

但很快发现一个问题:跳过 PIE(SkipPIE 模式)不是正确的验收流程。跳过真实启动路径意味着验收意义存疑——我们要验证的是玩家真正能走通,而不是函数逻辑正确。

于是换了个思路:让自动化跑在真实游戏会话里,走玩家同一条操作链

具体做法是在游戏内加一个 GM(Game Master / 调试命令)分发框架:控制台输入 gm <命令>,分发到注册的 Lua 处理函数。流程用例变成一条命令:

  • 确保在目标页签 → 点「开始」按钮 → 等场景切换 → 停留 N 秒 → 点「退出」 → 等回主界面。

每一秒轮询一次状态机,每个步骤带超时;通过 / 失败都有明确日志。

这样做的好处:

  • 不启停 PIE、不重启引擎,直接在当前会话里验证;
  • 走的就是玩家点击的按钮回调,链路完全一致;
  • 控制台日志带统一前缀,grep 即可过滤结果。

6. 关键技巧:如何模拟一次「真实点击」

需求升级后,自动化要求「像玩家一样点击」,而不是直接调用面板的处理函数。

第一个念头是找 SimulateClick 之类的接口——UE 的 UButton 并没有这个蓝图接口

翻源码发现:真实点击最终是 Slate 层广播按钮的点击委托OnClicked / OnButtonBaseClicked / OnTouchEnd / OnCustomMouseButtonUp 等),而 UnLua 把这些委托暴露为支持 Broadcast() 的委托对象。

所以:

delegate:Broadcast() 就是与真实点击同一触发路径的模拟点击。

实现上做了两个小工具:

  1. ClickButton(widget, preferEvent):按 OnClicked → OnButtonBaseClicked → OnTouchEnd → OnCustomMouseButtonUp 顺序广播,返回是否成功;
  2. 一个跨 Lua view 与 UserWidget 的按名递归找控件工具。

找控件的经验:优先用业务代码里已经缓存的字段(面板 CacheWidgets 里存的那批),找不到再按名字递归。列表条目(ListView / TileView 动态生成的)用面板自己维护的「按钮 → 条目」缓存映射,比重新遍历列表可靠得多。


7. 踩坑速查表

解法 详见
UE 5.7 命令改名 RunUnreal 而非 Gauntlet §2
源码引擎重编 UAT 崩 -nocompileuat §2
控制台跑测试带引号匹配不到 过滤参数不带引号 §2
Lua 模块名带前缀 require 不到 模块名与磁盘路径对齐 §4
多行错误破坏日志解析 错误文本折叠成单行 §4
UnLua TArray 不能用 # :Num() + 1 基下标 §4
SkipPIE 不是有效验收 改用游戏内 GM 驱动真实会话 §5
UButton 没有 SimulateClick 广播按钮点击委托(与真实点击同路径) §6

8. 三条原则

  1. 优先走玩家真实操作链。宁可牺牲一点隔离性,也要保证验收有效性。「跳过 PIE」「直接调函数」这类捷径,验收价值都会打折扣。

  2. 分层跑,速度分层。毫秒级逻辑单测当回归主力,秒级模块冒烟每次跑,分钟级流程用例按需跑,端到端留给 CI。

  3. 每一步自动化都要能被日志讲清楚。哪个按钮、哪个回调、哪一步、超时多少,出问题时日志就是唯一的诊断线索。配套一个「控件树打印」命令,UI 结构对不上时一键导出,非常省事。


9. 小结与下一篇

自动化测试不是「写几个用例」就完了。把链路打通、把日志讲清楚、让验收真正有效,才是它值钱的地方。

下一篇Android 真机执行、报告回传与性能/闪退采集——讲怎么把「编辑器里能验收」推进到「真机也能稳定跑并留下可复盘的报告」,含 14 条真机踩坑速查表。

posted @ 2026-08-26 14:40  ReseeLei  阅读(47)  评论(0)    收藏  举报