DSL 动作列表
Tapilot DSL v0.3 共 36 个动作。
应用控制
| 动作 | 参数 | 示例 |
|---|---|---|
launch | {package, force?, clearData?} | launch: { package: com.example.app, force: true } |
installApp | string (path) | installApp: /tmp/MyApp.app |
uninstallApp | string (package) | uninstallApp: com.example.app |
terminateApp | string (package) | terminateApp: com.example.app |
openUrl | string | openUrl: "https://example.com" |
交互
| 动作 | 参数 | 示例 |
|---|---|---|
tap | string 或 {x, y} | tap: Settings 或 tap: { x: 540, y: 1200 } |
tapNthOf | {class, index} | tapNthOf: { class: android.widget.EditText, index: 0 } |
swipe | 方向或坐标 | swipe: up 或 swipe: { fx: 540, fy: 1800, tx: 540, ty: 600 } |
scroll | {direction, times?} | scroll: { direction: down, times: 3 } |
scrollUntil | {label, direction?, maxScrolls?} | scrollUntil: { label: About, direction: down } |
swipeUntil | {label, direction?, maxSwipes?} | swipeUntil: { label: Checkout, direction: left, maxSwipes: 5 } |
input | string | input: "hello world" |
press | string | press: KEYCODE_ENTER |
back | — | back |
home | — | home |
等待
| 动作 | 参数 | 示例 |
|---|---|---|
wait | integer (ms) | wait: 2000 |
waitStable | {timeoutMs?, hammingMax?} | waitStable: { timeoutMs: 5000 } |
waitFor | string 或 {pattern, regex?, timeoutMs?, intervalMs?} | waitFor: 加载完成 |
waitAbsent | 同上 | waitAbsent: Loading |
dismissModal | {maxRounds?} | dismissModal: { maxRounds: 3 } |
waitFor / waitAbsent 轮询 UI XML(间隔默认 500ms,超时默认 10s),直到 pattern 出现/消失。替代脆弱的 wait: 固定毫秒。
断言
| 动作 | 参数 | 示例 |
|---|---|---|
assert | string | assert: Welcome |
assertAbsent | string | assertAbsent: Error |
assertVisual | string | assertVisual: 页面显示了登录表单 |
assertCount | {class, min?, max?} | assertCount: { class: android.widget.Button, min: 2 } |
assertVisible | string | assertVisible: Login |
assertClickable | string | assertClickable: Submit |
assertEnabled | string | assertEnabled: Save |
assertFocused | string | assertFocused: Username |
assertSelected | string | assertSelected: Tab1 |
读屏 & 运行时变量
通过 readText 把屏上内容读到变量,后续 step 用 ${VAR} 引用。
| 动作 | 参数 | 示例 |
|---|---|---|
readText | {label, into} 或 {regex, into} | readText: { label: 您的验证码是, into: CODE } |
yaml
# 场景:OTP 验证码回填
- tap: 发送验证码
- wait: 3000
- readText: { regex: "(\\d{6})", into: CODE } # 从屏 XML 里匹配 6 位数字
- tap: { className: android.widget.EditText, index: 1 }
- input: "${CODE}"
- tap: 登录label模式:找到匹配的节点,取其text/content-desc(Android)或value/label/name(iOS)regex模式:对整个 UI XML 做正则匹配,取 group 1(无 group 则取全匹配)into必须是大写变量名(如CODE、ORDER_ID);与 parse 时的vars独立,不会冲突
数据驱动 forEach(CSV / JSON)
yaml
# users.csv:
# email,password,expected
# [email protected],pw1,Welcome alice
# [email protected],pw2,Welcome bob
steps:
- forEach:
var: U
from: ./users.csv # 相对 YAML 文件的路径,也支持绝对路径
steps:
- input: "${U.email}"
- tap: Next
- input: "${U.password}"
- tap: Login
- assert: "${U.expected}"from支持.csv(第一行表头,之后每行一条记录)或.json(数组,元素可以是 string 或 object)- CSV 多列时,子步骤用
${VAR.col}引用字段;JSON 对象同理 - JSON array of strings / CSV 单列时,直接用
${VAR}引用当前值 values和from互斥,二选一
控制流
| 动作 | 参数 | 示例 |
|---|---|---|
ifExists | {pattern, then, else?} | 见下方 |
repeat | {times, steps} | 见下方 |
forEach | {var, values | from, steps} | 见下方(支持静态 list 或 CSV/JSON 文件) |
工具
| 动作 | 参数 | 示例 |
|---|---|---|
setLocale | string | setLocale: zh-CN |
saveScreenshot | string | saveScreenshot: home-page |
executeJs | string | executeJs: "document.title" |