高级篇
掌握脚本、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 = 30shell:evalScript 的简写
shell 和 evalScript 功能完全相同,只是写法更短(注意:这不是操作系统的命令行,而是执行 JavaScript):
yaml
- shell: "counter = counter + 1"evalScript、runScript、shell 的区别
| evalScript | runScript | shell | |
|---|---|---|---|
| 写法 | 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 | 字符串 | 选填 | GET | HTTP 方法(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: "提交成功"如果 tapOn 或 assertVisible 失败,会重新从 tapOn 开始执行,最多再试 2 次。
不写 maxRetries 时默认为 1(失败后重试 1 次,总共尝试 2 次)。
限制:
maxRetries最大值为 3。file和commands不能同时使用。
设备控制
设置 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 秒打开链接 openLink
通过 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需要快速查命令?→ 命令速查表
