limrun-maestro-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Maestro on Limrun iOS

在Limrun iOS上运行Maestro

Run the stock upstream Maestro CLI against a remote Limrun iOS simulator.
lim ios maestro
wires
maestro test
to the instance transparently: it installs and launches the Maestro XCTest runner on the simulator when needed, then routes the driver traffic to it. No fork of Maestro, no local simulator, no local Xcode.
直接使用官方原生Maestro CLI对接远程Limrun iOS模拟器。
lim ios maestro
会自动将
maestro test
与模拟器实例关联:在需要时,它会在模拟器上安装并启动Maestro XCTest runner,然后将驱动流量路由至该runner。无需fork Maestro,无需本地模拟器,也无需本地Xcode。

Prerequisites

前提条件

  • lim
    CLI 0.22.0 or newer:
    npm install --global lim
    . Auth is
    lim login
    or
    LIM_API_KEY
    (it may be set outside the project, so don't ask for it just because it's missing from
    .env
    or the shell).
  • Maestro CLI on PATH:
    curl -fsSL https://get.maestro.mobile.dev | bash
    . Maestro needs Java 17+ (
    java -version
    to check). Both Maestro 2.5.x and 2.6+ work;
    lim
    adapts to the installed version automatically.
The CLI is the source of truth: if a flag errors or you need one not shown here, check
lim ios <subcommand> --help
instead of guessing.
  • lim
    CLI 0.22.0或更高版本:执行
    npm install --global lim
    安装。认证方式为
    lim login
    或设置
    LIM_API_KEY
    (该密钥可在项目外配置,因此不要仅因
    .env
    或Shell中未配置就索要)。
  • 系统PATH中需配置Maestro CLI:执行
    curl -fsSL https://get.maestro.mobile.dev | bash
    安装。Maestro需要Java 17+版本(可通过
    java -version
    检查)。Maestro 2.5.x和2.6+版本均兼容;
    lim
    会自动适配已安装的版本。
CLI是权威参考:若某个标记报错或需要此处未展示的标记,请查看
lim ios <subcommand> --help
,不要自行猜测。

Verify the setup

验证环境配置

Before touching the user's app, prove the whole pipeline with a flow against the built-in Settings app; it needs no app install, tunnel, or build:
bash
ID=$(lim ios create --install-asset appstore/maestro-ios-runner-2.5.1.tar.gz \
  --no-open --quiet --json | jq -r .metadata.id)

cat > hello-flow.yaml <<'EOF'
appId: com.apple.Preferences
---
- launchApp
- assertVisible: General
- takeScreenshot: settings-check
EOF

lim ios maestro --id "$ID" test hello-flow.yaml
All three steps reporting
COMPLETED
means Maestro, the runner, and the remote wiring all work; anything failing after this point is about the app or the flow, not the setup.
在操作用户的应用之前,先通过内置“设置”应用的流程验证整个链路是否正常;该流程无需安装应用、配置隧道或构建:
bash
ID=$(lim ios create --install-asset appstore/maestro-ios-runner-2.5.1.tar.gz \
  --no-open --quiet --json | jq -r .metadata.id)

cat > hello-flow.yaml <<'EOF'
appId: com.apple.Preferences
---
- launchApp
- assertVisible: General
- takeScreenshot: settings-check
EOF

lim ios maestro --id "$ID" test hello-flow.yaml
若三个步骤均显示
COMPLETED
,则说明Maestro、runner和远程连接均正常工作;此后出现的任何问题都与应用或流程本身有关,而非环境配置问题。

Run a flow

运行流程

bash
lim ios maestro test flow.yaml
lim ios maestro test flows/
lim ios maestro --id <ios-id> test flow.yaml
Without
--id
this targets the most recently created iOS instance in the current workspace (workspaces follow the git repo or worktree you run from); pass
--id <ios-id>
(before
test
) in scripts, agents, or when running from a different directory. The first run on an instance takes a few extra seconds to launch the runner (plus the install when it wasn't preinstalled); later runs skip that. Extra Maestro flags go after
--
:
bash
lim ios maestro -- test flow.yaml --include-tags smoke --test-output-dir artifacts
Do not pass
--platform
,
--device
,
--udid
,
--no-reinstall-driver
, or
--driver-host-port
;
lim
sets those itself and rejects duplicates. Real Maestro exit codes and reports are preserved, so CI wiring works as with local Maestro.
bash
lim ios maestro test flow.yaml
lim ios maestro test flows/
lim ios maestro --id <ios-id> test flow.yaml
若未指定
--id
,则会针对当前工作区中最近创建的iOS实例(工作区与您运行命令所在的Git仓库或工作树关联);在脚本、Agent或从其他目录运行时,请在
test
之前传入
--id <ios-id>
。首次在实例上运行时,需要额外几秒时间启动runner(若未预安装runner,还需额外安装时间);后续运行则会跳过该步骤。额外的Maestro标记需放在
--
之后:
bash
lim ios maestro -- test flow.yaml --include-tags smoke --test-output-dir artifacts
请勿传入
--platform
--device
--udid
--no-reinstall-driver
--driver-host-port
lim
会自行设置这些标记,且会拒绝重复传入。Maestro的真实退出码和报告将被保留,因此CI集成方式与本地Maestro完全一致。

Instance setup

实例配置

Any running iOS instance works; the runner is installed on first use. Creating the instance with the runner preinstalled skips that step:
bash
lim ios create --install-asset appstore/maestro-ios-runner-2.5.1.tar.gz --no-open
--no-open
skips opening the stream URL in a browser (important on headless and CI machines). The runner asset name above is the only published one and it is version-agnostic: the same runner serves Maestro 2.5.x through 2.7.x, so do not look for an asset matching your Maestro version.
Install the app under test as usual (
lim ios create --install app.ipa
,
lim ios install-app
, or a build skill), then reference its bundle id via
appId:
in the flow. For Expo Go testing, also preinstall
appstore/Expo-Go-54.0.6.tar.gz
and open the project URL with
openLink
(env vars must be prefixed
MAESTRO_
to be visible in flows):
bash
MAESTRO_EXPO_URL='exp://<tunnel-host>' lim ios maestro test flow.yaml
任何运行中的iOS实例均可使用;runner会在首次使用时自动安装。创建实例时预安装runner可跳过安装步骤:
bash
lim ios create --install-asset appstore/maestro-ios-runner-2.5.1.tar.gz --no-open
--no-open
会跳过在浏览器中打开流URL(在无头环境和CI机器上非常重要)。上述runner资产名称是唯一已发布的版本,且与Maestro版本无关:同一个runner可支持Maestro 2.5.x至2.7.x版本,因此无需寻找与您安装的Maestro版本匹配的资产。
按照常规方式安装待测试应用(
lim ios create --install app.ipa
lim ios install-app
或使用构建skill),然后在流程中通过
appId:
引用其Bundle ID。若要测试Expo Go,还需预安装
appstore/Expo-Go-54.0.6.tar.gz
,并使用
openLink
打开项目URL(环境变量必须以
MAESTRO_
为前缀才能在流程中可见):
bash
MAESTRO_EXPO_URL='exp://<tunnel-host>' lim ios maestro test flow.yaml

Expo dev-client builds

Expo开发客户端构建

Expo Go is the quickest path, but a dev-client build works too.
launchApp
lands on the dev launcher rather than your app, so open the dev-client URL instead:
- stopApp
followed by
- openLink: <scheme>://expo-development-client/?url=<url-encoded-metro-url>
. Use
limrun-expo-development
for building the dev client, starting Metro, and deriving that URL.
Expo Go是最快的测试路径,但开发客户端构建也可正常使用。
launchApp
会直接进入开发启动器而非您的应用,因此需改为打开开发客户端URL:先执行
- stopApp
,再执行
- openLink: <scheme>://expo-development-client/?url=<url-encoded-metro-url>
。可使用
limrun-expo-development
构建开发客户端、启动Metro并生成该URL。

Flow gotchas on Limrun

Limrun上的流程注意事项

  • startRecording
    /
    stopRecording
    YAML commands are not supported (the simulator is remote). Record around the run instead:
    lim ios record start --id <ios-id>
    returns immediately (recording happens on the instance), and after the flow
    lim ios record stop --id <ios-id> -o video.mp4
    downloads the video to the local path.
  • takeScreenshot
    works and saves the PNG locally into the working directory (or
    --test-output-dir
    ), like stock Maestro.
  • addMedia
    and flow commands that reference local simulator file paths are not supported.
  • HTTP calls from
    runScript
    /
    evalScript
    must use
    https://
    URLs. Plain
    http://
    calls are refused (except to the driver itself), because Maestro's plain-HTTP traffic is routed through a local bridge that only forwards to the remote simulator.
  • When a flow re-runs against an app that is already open (for example Expo Go), start it with
    - stopApp
    before
    openLink
    /
    launchApp
    ; deep links can be dropped by an app that is mid-foreground, and stale screens fail early assertions.
  • Fleet variance: anchor assertions on stable accessibility identifiers and text, not on timing. Use
    extendedWaitUntil
    with a generous timeout for first app load.
  • Text selectors match the element's accessibility label, and on iOS a label often folds in sibling content (icon names, adjacent text) or non-breaking spaces. Read the exact label with
    lim ios element-tree
    before writing the selector instead of guessing from what the screen shows.
  • 不支持
    startRecording
    /
    stopRecording
    YAML命令(因为模拟器是远程的)。可在运行流程前后进行录制:
    lim ios record start --id <ios-id>
    会立即返回(录制在实例上进行),流程结束后执行
    lim ios record stop --id <ios-id> -o video.mp4
    即可将视频下载到本地路径。
  • takeScreenshot
    功能正常,会将PNG图片保存到本地工作目录(或
    --test-output-dir
    指定的目录),与原生Maestro一致。
  • 不支持
    addMedia
    及引用本地模拟器文件路径的流程命令。
  • runScript
    /
    evalScript
    中的HTTP调用必须使用
    https://
    URL。纯
    http://
    调用会被拒绝(除了对驱动本身的调用),因为Maestro的纯HTTP流量会通过本地桥接路由,而该桥接仅转发至远程模拟器。
  • 当流程针对已打开的应用(例如Expo Go)重新运行时,需在
    openLink
    /
    launchApp
    之前先执行
    - stopApp
    ;处于前台的应用可能会丢弃深度链接,且陈旧的界面会导致早期断言失败。
  • 设备差异:断言需基于稳定的可访问性标识符和文本,而非时间。首次加载应用时,使用
    extendedWaitUntil
    并设置充足的超时时间。
  • 文本选择器匹配元素的可访问性标签,而在iOS上,标签通常会包含兄弟内容(图标名称、相邻文本)或不间断空格。编写选择器前,请使用
    lim ios element-tree
    查看确切的标签,不要仅凭屏幕显示内容猜测。

Validation signals

验证信号

  • Running maestro <version> against <ios-id>...
    then
    Running on Limrun iPhone - iOS ...
    : the driver is connected end to end.
  • Launching the Maestro runner...
    : first use on this instance.
    Installing the Maestro runner...
    additionally appears only when the instance was created without the runner asset. Subsequent runs skip both.
  • Maestro itself prints several JDK
    WARNING
    lines (reflection, native access) on every run; they are benign upstream noise, not Limrun errors.
  • Flow failures print Maestro's own debug output directory with screenshots and the UI hierarchy;
    lim ios element-tree --id <ios-id>
    shows the live screen when debugging selectors.
  • 显示
    Running maestro <version> against <ios-id>...
    ,随后显示
    Running on Limrun iPhone - iOS ...
    :说明驱动已完成端到端连接。
  • 显示
    Launching the Maestro runner...
    :这是该实例的首次使用。若实例创建时未预安装runner资产,还会额外显示
    Installing the Maestro runner...
    。后续运行会跳过这两步。
  • Maestro每次运行时都会打印多条JDK警告信息(反射、原生访问);这些是上游的良性输出,并非Limrun的错误。
  • 流程失败时,Maestro会打印自身的调试输出目录,其中包含截图和UI层级;调试选择器时,
    lim ios element-tree --id <ios-id>
    可显示当前屏幕的实时内容。

Cleanup

清理

Delete the instance when done:
lim ios delete <ios-id>
(
--id
is not valid for delete). The wiring
lim ios maestro
starts is torn down when the command exits.
使用完毕后删除实例:
lim ios delete <ios-id>
delete
命令不支持
--id
标记)。
lim ios maestro
启动的连接会在命令退出时自动断开。