使用 makepad_test 为 Makepad 应用编写 Rust 原生 UI 回归测试
发布时间:2026/10/8 1:49:10 锦皓数字建站

前端UI组件3D渲染跨平台游戏开发【免费下载链接】makepadMakepad is a creative software development platform for Rust that compiles to wasm/webGL, osx/metal, windows/dx11 linux/opengl项目地址https://gitcode.com/gh_mirrors/ma/makepad点击查看免费下载导读makepad_test是 Makepad 官方为 Rust 应用提供的 UI 回归测试框架测试直接放在被测包旁边通过普通cargo test运行驱动一个独立启动的 release 应用经由其--remoteHTTP 面完成全部交互。默认情况下测试窗口隐藏、无需 Studio 实例或 hub 参与。读完本文你将掌握如何配置 dev-dependency、编写#[makepad_test]测试用例、使用 Selector 与 Locator 进行结构化快照匹配与断言、开启可见窗口调试模式以及利用失败产物artifact快速定位问题。快速开始三步接入现有包1. 添加 dev-dependency在被测包的Cargo.toml中声明[dev-dependencies] makepad-test { path ../../libs/makepad_test, version 0.1.0 }仓库中实际的用法可参考 examples/text_input 等示例包其tests/ui.rs即典型的包内集成测试。2. 创建集成测试在包目录下新建tests/ui.rs或任意tests/*.rs测试与被测包同处一室use makepad_test::{makepad_test, Selector, TestApp}; #[makepad_test] fn fill_and_submit(app: TestApp) { app.locator(Selector::id(input_singleline)) .wait_visible() .fill(hello) .wait_value(hello); app.press_return(); app.locator(Selector::id(status_label)) .wait_text(Returned from singleline: \hello\); }这个用例完整演示了 makepad_test 的典型节奏定位 → 等待可见 → 交互 → 等待状态断言。3. 运行包内测试套件cargo test --release -p makepad-example-text-input --test ui -- --test-threads1注意两点使用--release因为宏会自动执行cargo build --release -p package来构建被测应用使用--test-threads1保证套件顺序可预测原因见下文运行期默认值。想要实时观察窗口开启可见模式默认测试窗口是隐藏的通过MAKEPAD_HIDE_WINDOWS1。若想亲眼观察测试驱动应用的过程可开启可见模式窗口会保持不聚焦MAKEPAD_TEST_VISIBLE1 \ MAKEPAD_TEST_STARTUP_DELAY_MS1000 \ MAKEPAD_TEST_ACTION_DELAY_MS750 \ MAKEPAD_TEST_KEEP_OPEN_MS3000 \ cargo test --release -p makepad-example-text-input --test ui -- --test-threads1三个节奏环境变量的含义MAKEPAD_TEST_STARTUP_DELAY_MS1000应用启动后、测试开始前等待 1000msMAKEPAD_TEST_ACTION_DELAY_MS750每次交互后等待 750msMAKEPAD_TEST_KEEP_OPEN_MS3000测试结束后、关闭窗口前停留 3000ms。可见模式仍然使用自有进程传输绝不会连接既有应用或 Studio 会话同时 harness 会从子进程环境中移除MAKEPAD_FOCUS避免把窗口带到前台见 libs/makepad_test/src/app_process.rs 中launch的环境清理逻辑。运行模型owned 进程 --remote HTTP 面makepad_test 的核心运行模型是每个测试驱动一个完全属于自己owned的应用进程这与连接正在运行的 Studio 或既有实例的旧方案有本质区别从包目录执行cargo build --release -p package复用 Cargo 的 owning-workspace release target——继承环境中的CARGO_TARGET_DIR或显式配置的TestConfig::env[CARGO_TARGET_DIR]都会生效harness 不会为每个示例单独建立构建目录详见 libs/makepad_test/src/app_process.rs 的build_release_binary从 Cargo 的compiler-artifactJSON 消息流中选出该包的 bin 可执行文件select_executable以--remote启动该可执行文件隐藏窗口除非可见模式从应用的启动行[makepad-remote] listening on 127.0.0.1:PORT pid... app... grabs...中读取自有 PID 与临时端口等待应用打开第一个窗口后将TestApp传入测试体测试失败或 panic 时捕获失败产物请求/gqgrab and quit先保存最后一帧再退出必要时回退到/quit并确认自有子进程确实退出——只有优雅关闭超时后才会 kill 那个精确匹配的 PID。关键设计既有用户实例永远不会被复用、被停止或被驱动。launch还会校验监听行声明的 PID 必须与child.id()一致app_process.rs 的launch杜绝连错进程。子进程 stdout/stderr 直接写入产物目录文件因此无需读取线程且日志天然成为失败产物。API 总览Surface Areamakepad_test对外暴露四个核心构件见 libs/makepad_test/src/lib.rs构件用途#[makepad_test]当前包内 UI 测试的属性宏TestApp应用级输入、等待、日志、截图、底层输入转发Selector结构化快照匹配Locator严格单控件交互与断言库还重新导出了makepad_studio_protocol中的KeyCode、KeyModifiers、MouseButton、StudioToApp、WidgetSnapshot等类型以及TestConfig、run_with_config、WindowInfo、TestError/TestResult。支持的测试函数签名#[makepad_test]展开为一个普通#[test]包装函数测试体必须是同步的且恰好接收一个TestApp参数#[makepad_test] fn smoke(app: TestApp) { // ... } #[makepad_test] fn smoke(app: TestApp) - Result(), TestError { // ... Ok(()) }不支持的形态async 测试、带self的方法、泛型测试函数、宏参数见 libs/makepad_test/macros/src/lib.rs 的expand_makepad_test其中对 async/const/generics/多参数均返回编译错误。宏的展开行为#[makepad_test]展开为普通#[test]包装默认面向当前包env!(CARGO_MANIFEST_DIR)提供包目录env!(CARGO_PKG_NAME)提供要运行的包名。这保持了标准 Rust 工作流添加 dev-dependency、编写tests/*.rs、执行cargo test --release -p package。宏保留cfg等属性在包装函数上而ignore/should_panic等测试专用属性也被正确迁移到包装函数。若需针对其他包/清单可用run_with_config显式指定见 runtime.rs 的run_current_package_test与run_with_config。运行期默认值与配置运行期是同步、串行优先的libs/makepad_test/src/runtime.rs参数默认值启动超时等待监听行/首窗口600s动作超时wait_* 类断言10s轮询间隔50ms产物目录manifest_dir/target/makepad_test/package/test/拖拽步数6步插值日志保留最近200行串行锁运行器在每个测试可执行文件内部串行化应用会话——每个测试都要驱动一整个应用进程并行会过度占用机器资源并使时序敏感断言变得不稳定。--test-threads1保证套件顺序可预测MAKEPAD_TEST_PARALLEL1可在套件被设计为并发运行多个自有实例时选择退出锁env_truthy接受1/true/yes/on。显式配置TestConfig除环境变量外也可显式构造配置let mut config TestConfig::current_package(manifest_dir, package_name, test_name)?; config.bin_name Some(other-bin); // 多 bin 包中选定目标 config.app_args.push(--flag); // 追加在 --remote 之后的参数 config.visible true; config.env.insert(CARGO_TARGET_DIR.to_string(), /tmp/target.to_string()); run_with_config(config, |app| { /* ... */ })字段说明见 runtime.rs 的TestConfig结构体bin_name包内构建出多个 bin 时选择启动目标app_args追加在--remote之后的命令行参数visible窗口可见性env中默认注入RUST_BACKTRACE1env[CARGO_TARGET_DIR]同时作用于构建与应用进程env[MAKEPAD_GPUSIM_DPI]设为正数可将截图缩放到该像素密度用于既有套件不会选择软件渲染器也不改变原生窗口 DPI。注意旧的mount_name、listen_address字段及MAKEPAD_TEST_STUDIO/MAKEPAD_TEST_STUDIO_MOUNT设置已不再适用——没有 hub 或 mount 需要配置。Selector结构化快照匹配Selector 基于快照工作匹配结构化控件状态而非仅依赖几何查询串实现见 libs/makepad_test/src/selector.rs。构造函数构造器说明Selector::all()匹配所有控件Selector::id(widget_id)按控件 id 匹配Selector::widget_type(TextInput)按控件类型匹配Selector::raw(text:hello)按原始查询串匹配builder 过滤器可链式组合.text_exact(...)text/value/selected 任一字段精确相等.text_contains(...)任一文本字段包含子串.nth(index)在第 N 个匹配上继续.window(panel_window)限定窗口 id.window_index(1)限定窗口下标.any_window()不限窗口。Selector 默认限定在主窗口primary_window_scope取快照中最小窗口下标/窗口 id单窗口测试因此可以写得非常简洁多窗口场景再显式指定。raw查询支持带前缀形式id:、type:、text:、value:、window:无前缀时则对 id、类型、窗口 id 及全部文本字段做包含匹配见matches_raw。Locator严格的单控件交互与断言Locator方法要求恰好一个可见匹配才能交互——这是刻意设计避免测试在不知不觉中点击到错误的控件。多个匹配或零匹配都会得到明确的TestErrorruntime.rs 的unique会列出所有匹配的摘要。常见交互动作app.locator(Selector::id(panel_input)) .wait_visible() .fill(hello) .wait_value(hello) .press_key(KeyCode::ReturnKey);可用动作click、type_text先点击再逐字输入、fillclear 后输入、clear点击后Ctrl/CmdABackspace主修饰键按平台选择、press_key、press_key_with_modifiers、scroll(sx, sy)、drag_by(dx, dy)6 步插值移动。等待与断言等待wait_*轮询至超时断言assert_*立即校验wait_visible/wait_hidden/wait_count—wait_text/wait_value/wait_checked/wait_enabledassert_text/assert_value/assert_checked/assert_enabled等待实现会持续轮询快照直到期望状态达成或action_timeout超时超时错误信息中会附上最后一次看到的值last seen ...方便定位卡点。检查辅助snapshot()返回当前匹配的完整WidgetSnapshotcount()可见匹配数量widget_snapshot()整个应用的结构化快照VecWidgetSnapshotwidget_dump()原始紧凑控件树文本screenshot()将主窗口抓取为 PNG返回应用自身 grab 目录中的路径wait_for_log_contains(...)等待应用日志中出现指定内容。底层逃生通道forwardapp.forward(vec![/* pointer、scroll、key 或 text 的 StudioToApp 事件 */]);forward会把受支持的输入事件翻译为 HTTP 输入路由其他历史协议变体返回显式错误例如MouseCancel会被拒绝——测试客户端没有 cancel 输入重放成 up 会造成误点击。注入时分配原生时间戳不支持键重复与 IME 元数据也不提供热重载、窗口缩放、swapchain、剪贴板转发或 hub 控制。常规场景请优先使用TestApp的标准方法。结构化控件状态每次快照记录暴露remote.rs 的parse_snapshot控件 id、控件类型boundsr窗口局部布局坐标已取整为整数window id 与 window indexvisible / enabled 状态控件特有状态可用时text、value、checked、selected。窗口名、enabled 与 selected 来自真实控件快照缺失必需字段会解码失败而不是伪造状态。可选状态在控件不暴露时缺席空标签可能省略text而空输入框的value保留为空字符串。关于可见性的一个精妙设计resolve_unique_readable见 runtime.rs交互要求可见几何但状态读取优先可见匹配当无可见匹配时可以回退到唯一匹配的被裁剪clipped控件——例如滚动页面折叠线以下的标签、长表单底部的状态标签它们没有屏幕矩形、不可点击但状态完全可读、值得断言。失败产物Failure Artifacts产物是包内独立的与共享的 Cargo 构建目标分离manifest_dir/target/makepad_test/package/test/构建阶段写入build-stderr.txt启动的会话额外写入app-stdout.txt、app-stderr.txt与shutdown.txt记录自有 PID 与关闭结果graceful / already exited / killed。测试体失败还会捕获failure.txt失败消息logs.txt应用日志尾部最近 200 行widget-snapshot.json结构化快照widget-tree.txt或widget-tree-error.txt原始控件树failure-screenshot.png或failure-screenshot-error.txt失败现场截图。任何捕获步骤失败时运行器都会写一个*-error.txt文件而不是静默丢弃产物runtime.rs 的capture_failure_artifacts。独立传输与进程所有权Standalone Transport and Ownership运行期使用应用文档化的 HTTP remote 面见 docs/agents/app-remote.md/s窗口状态、/snap快照、/d控件树、/g抓图、/log日志与输入路由/click、/m、/k、/t。输入请求会等待一个结果帧返回。矩形坐标是窗口局部布局点点击时不要做 DPI 换算。截图取自应用自己的 drawable。TestConfig::env[MAKEPAD_GPUSIM_DPI]设为正数时截图按该像素密度缩放scale dpi / window.dpi。清理流程先/gq保存最后一帧并退出若抓图不可用或应用未退出发送/quit。丢失的响应不视为进程未退出的证据——运行器等待自有Child句柄只有优雅关闭超时才 kill 该精确子进程。该清理在测试 panic 后同样执行。它从不停止、替换或驱动用户自有实例。另外注意closed by user响应会被保留为错误运行器不会重启被用户关闭的应用抓图请求的超时更长后端需完成 readback 与 PNG 编码。故障排查速查表测试超时 / 无法解析控件查看target/makepad_test/.../logs.txt查看widget-snapshot.json中的 text/value/checked/selected 状态查看widget-tree.txt的原始紧凑树检查 Selector 是否圈定得足够紧是否存在多个匹配。启动失败查看build-stderr.txt、app-stdout.txt、app-stderr.txt。确认关闭路径查看shutdown.txt确认是正常退出还是走了精确 PID 兜底 kill。测试内实时诊断app.pid()、app.remote_endpoint()、app.grab_dir()只标识该自有实例。当前限制Current Constraints仅同步 API宏默认面向当前包run_with_config可指定其他清单/包forward支持 pointer、scroll、key、text其他历史协议消息返回错误控件快照需要当前 remote 字段window_id与布尔enabled可选selected会被保留milestone-1 仓库套件首先在 macOS 上验证其他平台后端在抓图支持上可能不同尚无视觉 diff 与 trace viewer。完整的技术细节包括完整的编写模型、运行期行为与排障笔记可继续阅读 libs/makepad_test/GUIDE.md宏展开的具体约束可参阅 libs/makepad_test/macros/src/lib.rs运行期实现可参阅 libs/makepad_test/src/runtime.rs。赞分享前端UI组件3D渲染跨平台游戏开发【免费下载链接】makepadMakepad is a creative software development platform for Rust that compiles to wasm/webGL, osx/metal, windows/dx11 linux/opengl项目地址https://gitcode.com/gh_mirrors/ma/makepad点击查看免费下载相关推荐Baserow 配置全景指南从 URL、密钥到 Webhook 限速的全量环境变量解析Baserow 配置全景指南从 URL、密钥到 Webhook 限速的全量环境变量解析 Baserow 的所有行为——从对外访问地址、数据库与 Redis 连前端UI组件3D渲染跨平台游戏开发使用 react-native-windows/automation 为 React Native Windows 应用编写端到端 UI 测试使用 react native windows/automation 为 React Native Windows 应用编写端到端 UI 测试 导读 rea跨平台前端如何为 rustc 的 bug 修复编写 UI 回归测试tests/ui 文件结构、directives 与 --bless如何为 rustc 的 bug 修复编写 UI 回归测试tests/ui 文件结构、directives 与 bless 在 rustc 的开发流程中rus编程语言编译器语言运行时标准库上一篇魔兽争霸III终极优化指南5分钟让你的经典游戏焕发新生下一篇GSD-2 切片完成后的路线图重估reassess-roadmap 单元的原理、判定流程与 MCP 工具实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。