Skip to content

高级篇

掌握脚本、HTTP 请求、坐标操作等高级功能。


JavaScript 脚本 evalScript / runScript / shell

在流程中执行 JavaScript 代码,实现复杂逻辑。

evalScript:直接执行表达式

yaml
# 计数器加 1
- evalScript: "${counter = counter + 1}"

# 拼接字符串
- evalScript: "${fullName = firstName + ' ' + lastName}"

# 定义数组
- evalScript: "${items = ['苹果', '香蕉', '橘子']}"

# 随机选择数组元素
- evalScript: "${selected = items[Math.floor(Math.random() * items.length)]}"

# 复杂运算
- evalScript: "${score = Math.floor(Math.random() * 100) + 1}"

runScript:带变量注入的脚本

yaml
- runScript:
    script: "result = a + b"
    env:
      a: "10"
      b: "20"
# 执行后 result = 30

shell:evalScript 的简写

shellevalScript 功能完全相同,只是写法更短(注意:这不是操作系统的命令行,而是执行 JavaScript):

yaml
- shell: "counter = counter + 1"

evalScript、runScript、shell 的区别

evalScriptrunScriptshell
写法evalScript: "${表达式}"runScript: { script: "...", env: {...} }shell: "脚本"
变量注入不支持支持 env 注入不支持
适用场景简单的单行表达式需要注入外部变量的脚本evalScript 的简写

内置可用对象

脚本中可以使用的标准 JavaScript 对象:

yaml
# Math 数学函数
- evalScript: "${x = Math.floor(Math.random() * 100)}"
- evalScript: "${y = Math.max(10, 20)}"
- evalScript: "${z = Math.pow(2, 8)}"

# 字符串操作
- evalScript: "${upper = 'hello'.toUpperCase()}"
- evalScript: "${part = 'hello world'.substring(0, 5)}"
- evalScript: "${arr = 'a,b,c'.split(',')}"

# JSON 操作
- evalScript: "${obj = JSON.parse('{\"name\":\"test\"}')}"
- evalScript: "${str = JSON.stringify(obj)}"

# 类型判断
- evalScript: "${type = typeof counter}"

assertTrue:验证脚本条件

yaml
- assertTrue: "${counter > 0}"
- assertTrue: "${status == 'success'}"

剪贴板操作

注意:这里的剪贴板是引擎自带的剪贴板,不是 Android 系统剪贴板。

从元素复制文字 copyTextFrom

yaml
- copyTextFrom:
    text: "用户名"               # 复制显示"用户名"的元素的文字内容

复制后,文字存入 copiedText 变量,可通过 ${copiedText} 引用。

粘贴 pasteText

yaml
- pasteText                      # 输入之前复制的文字

手动设置剪贴板 setClipboard

yaml
- setClipboard: "自定义内容"

- pasteText                      # 输入"自定义内容"

完整示例:复制并使用

yaml
- copyTextFrom: { id: "verification_code" }
- tapOn: "验证码输入框"
- pasteText

随机输入

生成随机数据并输入,适用于测试场景。

随机文字

yaml
- inputRandomText                # 8 个随机字母(默认)

- inputRandomText:
    length: 16                   # 16 个随机字母

随机数字

yaml
- inputRandomNumber:
    length: 6                    # 6 位随机数字,如 "483729"

随机邮箱

yaml
- inputRandomEmail               # 生成类似 john.doe@example.com 的邮箱

随机人名

yaml
- inputRandomPersonName           # 生成随机人名

HTTP 请求 httpRequest

在流程中发起 HTTP 请求,获取外部数据。

所有参数

参数类型必填默认值说明
url字符串必填请求 URL
method字符串选填GETHTTP 方法(GET、POST 等)
headers对象选填请求头键值对
body对象选填请求体
outputVariable字符串选填将响应结果存入的变量名
jsonPath字符串选填从 JSON 响应中提取的路径
retry.times数字选填1最大重试次数
retry.interval数字或数组选填3000重试间隔(ms),支持 [min, max] 随机

GET 请求

yaml
- httpRequest:
    url: "https://api.example.com/sms?phone=${PHONE}"
    outputVariable: code          # 将结果存入 code 变量
    jsonPath: "data.code"         # 从 JSON 中提取 data.code 字段

POST 请求

yaml
- httpRequest:
    url: "https://api.example.com/login"
    method: POST
    headers:
      Content-Type: "application/json"
      Authorization: "Bearer ${TOKEN}"
    body:
      phone: "${PHONE}"
      password: "${PASSWORD}"
    outputVariable: result
    jsonPath: "data.token"

带重试的请求

某些接口可能不会立即返回结果(比如等短信验证码),可以自动重试:

yaml
- httpRequest:
    url: "https://api.example.com/sms/latest?phone=${PHONE}"
    outputVariable: smsCode
    jsonPath: "data.code"
    retry:
      times: 10                   # 最多重试 10 次(默认 1)
      interval: [3000, 5000]      # 每次间隔 3~5 秒(默认 3000 ms)

重试触发条件:当 jsonPath 提取结果为空或 null 时自动重试。

完整示例:自动获取验证码

yaml
# 1. 请求发送验证码
- httpRequest:
    url: "https://api.example.com/sms/send"
    method: POST
    body:
      phone: "${PHONE}"

# 2. 等几秒后查询验证码
- sleep: 3000

# 3. 获取验证码(带重试)
- httpRequest:
    url: "https://api.example.com/sms/latest?phone=${PHONE}"
    outputVariable: code
    jsonPath: "data.code"
    retry:
      times: 5
      interval: [2000, 4000]

# 4. 输入验证码
- inputText: "${code}"

坐标点击

当元素无法通过文字或 ID 定位时,可以直接用坐标点击。

绝对坐标(像素)

yaml
- tapOn:
    point: "360,800"             # 点击 x=360, y=800 的位置

百分比坐标(屏幕比例)

yaml
- tapOn:
    point: "50%,80%"             # 点击屏幕宽度 50%、高度 80% 处

百分比坐标的优势:不依赖屏幕分辨率,在不同设备上表现一致。

元素内相对坐标

在元素范围内的指定位置点击:

yaml
# 点击滑块的 25% 位置(偏左)
- tapOn:
    text: "音量"
    point: "25%,50%"             # 元素宽度 25% 处,高度 50% 处

坐标滑动

yaml
- swipe:
    start: "100,800"
    end: "100,200"               # 从 (100,800) 滑到 (100,200)
    duration: 300

# 百分比坐标
- swipe:
    start: "50%,80%"
    end: "50%,20%"
    duration: 400

容器内滚动

在指定容器内滚动查找元素,滑动范围限制在容器边界内。

yaml
- scrollUntilVisible:
    element:
      text: "目标商品"
    from:                        # 在这个容器内滚动
      id: "product_list"
    direction: UP
    timeout: "20000"

重试 retry

当一组命令可能偶尔失败时,自动重试。

yaml
- retry:
    maxRetries: "2"              # 失败后最多重试 2 次(总共尝试 3 次)
    commands:
      - tapOn: "提交"
      - assertVisible: "提交成功"

如果 tapOnassertVisible 失败,会重新从 tapOn 开始执行,最多再试 2 次。

不写 maxRetries 时默认为 1(失败后重试 1 次,总共尝试 2 次)。

限制maxRetries 最大值为 3。filecommands 不能同时使用。


设备控制

设置 GPS 位置

yaml
- setLocation:
    latitude: "39.9042"          # 纬度(北京)
    longitude: "116.4074"        # 经度

飞行模式

yaml
- setAirplaneMode:
    enabled: true                # 开启飞行模式

- setAirplaneMode:
    enabled: false               # 关闭飞行模式

# 简写形式
- setAirplaneMode: true          # 开启
- setAirplaneMode: false         # 关闭

截图 takeScreenshot

yaml
- takeScreenshot: /tmp/screen.png

将当前屏幕截图保存到指定路径。


等待动画结束

等待屏幕上的动画或过渡效果完成。

yaml
- waitForAnimationToEnd          # 默认最多等 15 秒

- waitForAnimationToEnd:
    timeout: 5000                # 自定义超时:5 秒

通过 URL 打开网页,或通过 App 专属链接直接跳转到 App 的特定页面。

yaml
# 打开网页
- openLink: "https://example.com"

# 打开 App 专属链接(直接跳转到 App 内的指定页面)
- openLink:
    link: "myapp://settings/profile"
    autoVerify: true
    browser: false               # 不要用浏览器打开

权限设置 setPermissions

批量设置 App 权限。

yaml
- setPermissions:
    appId: com.example.app
    permissions:
      android.permission.CAMERA: allow
      android.permission.LOCATION: allow
      android.permission.MICROPHONE: deny

也可以在 launchApp 时设置:

yaml
- launchApp:
    appId: com.example.app
    permissions:
      android.permission.CAMERA: allow

流程开始/结束时自动执行 onFlowStart / onFlowComplete

可以配置在流程开始前和结束后自动执行的命令。

yaml
appId: com.example.app
onFlowStart:
  - launchApp                    # 流程开始前自动启动 App
onFlowComplete:
  - stopApp                     # 流程结束后自动停止 App(无论成功失败)
---
- tapOn: "登录"
- inputText: "${PASSWORD}"
配置项执行时机特点
onFlowStart命令区执行之前用于初始化
onFlowComplete命令区执行之后无论成功失败都会执行,用于清理

高级实战:自动化测试 — 电商 App 浏览与下单

yaml
appId: com.example.shop
name: 电商 App 自动化测试

---
# 预定义测试搜索词
- evalScript: "keywords = ['手机壳', '数据线', '耳机', '充电宝', '键盘']"

- launchApp
- assertVisible: "首页"

# ── 阶段1:浏览商品列表 ──
- repeat:
    duration: "30000"
    commands:
      - swipe:
          direction: UP
          duration: [200, 500]
          waitToSettleTimeoutMs: 0
      - sleep: [2000, 4000]

# ── 阶段2:搜索并查看商品详情 ──
- tapOn: "搜索"
- inputText: "${keywords[Math.floor(Math.random() * keywords.length)]}"
- pressKey: Enter
- sleep: 2000

- repeat:
    times: "3"
    commands:
      - swipe:
          direction: UP
          duration: [200, 500]
          waitToSettleTimeoutMs: 0
      - sleep: [2000, 4000]

      # 50% 概率点击查看详情
      - tapOn:
          text: "查看详情"
          optional: true
          chance: 0.5

      - sleep: [1000, 3000]

      # 返回列表
      - back

# ── 阶段3:模拟下单流程 ──
- runFlow:
    commands:
      - tapOn:
          text: "加入购物车"
          optional: true
      - tapOn:
          text: "购物车"
          optional: true
      - assertVisible:
          text: "结算"
          optional: true
      - takeScreenshot: /tmp/cart_result.png

- stopApp

需要快速查命令?→ 命令速查表

VMOS Edge 团队出品