前言

在上一篇文章中,我们详细讲解了 Midscene.js 与 Playwright 测试框架的集成方式——通过 Fixture 注入 AI 能力,在 TypeScript 测试用例中调用自然语言驱动的操作方法。这种模式功能强大,适合专业的自动化测试工程师。

但对于一些简单场景,比如快速验证某个页面流程是否正常、批量执行回归检查,或者团队中有不熟悉 TypeScript 的同学也想参与自动化编写,写一整套 Playwright 测试项目就显得有些"重"了。

为此,Midscene.js 提供了一种更轻量的方式——YAML 脚本模式。你只需要写一个 .yaml 文件,用自然语言描述操作步骤,然后通过命令行工具一键执行即可。无需编写任何JavaScript/TypeScript 代码,无需搭建测试框架,真正做到"零代码"自动化。

本文将从 YAML 脚本运行器 和 YAML 格式的工作流 两个方面,深入讲解这种模式的使用方法。

一、YAML脚本运行器

Midscene 提供了一个命令行工具 @midscene/cli,可以解析并执行 .yaml 格式的自动化脚本。它支持的平台包括 Web 浏览器、Android、iOS、HarmonyOS,以及桌面端。本次记录的是web浏览器的YAML使用过程。

1.1安装

全局安装(推荐新手体验):

npm i -g @midscene/cli

全局安装后,可以在任意目录下直接使用 midscene 命令。

项目内安装(推荐正式项目):

npm i @midscene/cli --save-dev

项目内安装后,通过 npx midscene 调用。

Node.js 版本要求:20.19+、22.12+ 或 24+。CLI 部分执行路径依赖 Rstest/Rspack 工具链,旧版本的 Node 20 patch 可能不兼容。

1.2配置环境

与 Playwright 集成模式一样,YAML 脚本模式也需要通过 .env 文件配置 AI 模型:

# .env 文件,放置在命令执行目录下
MIDSCENE_MODEL_BASE_URL="https://api.openai.com/v1"
MIDSCENE_MODEL_API_KEY="sk-your-api-key"
MIDSCENE_MODEL_NAME="gpt-4o"
MIDSCENE_MODEL_FAMILY="gpt-4o"

Midscene 使用 dotenv 自动加载 .env 文件。注意:

  • 不需要 export 前缀(和 shell 脚本的写法不同)
  • 默认不会覆盖系统已有的同名环境变量(如需覆盖,加 --dotenv-override)
  • 可用 --dotenv-debug 开启 dotenv 调试日志

1.3编写第一个YAML脚本

创建一个 eBay-search.yaml 文件:

web:
  url: https://www.ebay.com

tasks:
  - name: 搜索耳机
    flow:
      - ai: 在搜索框中输入 "蓝牙耳机",然后点击搜索按钮
      - sleep: 3000
      - aiAssert: 页面上显示了蓝牙耳机信息

这个脚本的含义非常直观:

  1. 打开eBay首页
  2. 用 AI 驱动在搜索框输入"蓝牙耳机"并搜索
  3. 等待 3 秒让页面加载
  4. 断言页面上出现了蓝牙耳机结果

1.4脚本运行

# 全局安装
midscene ./bing-search.yaml

# 项目内安装
npx midscene ./bing-search.yaml

执行完成后,Midscene 会在当前目录的 midscene_run/ 下生成:

1.5命令行参数详解

midscene 命令提供了丰富的参数来控制执行行为:

基本执行控制

# 执行单个脚本
midscene ./test.yaml

# 通配符批量执行
midscene './scripts/**/*.yaml'

# 指定文件列表(按顺序执行)
midscene --files ./login.yaml ./search.yaml ./logout.yaml

-files
指定脚本文件列表,支持 glob 通配符。文件按字典序排序后依次执行。

--concurrent <number>
设置并发执行数量,默认为 1(串行)。如果你的 AI 模型 API 并发配额充足,可以适当增大以提高效率:

midscene --files './scripts/*.yaml' --concurrent 4

--continue-on-error
默认情况下,某个脚本失败会终止整个批次。加上此参数后,失败的脚本会被跳过,继续执行后续脚本:

midscene --files './scripts/*.yaml' --continue-on-error

--retry <number>
失败脚本的重试次数,默认为 0。注意:与 --share-browser-context 同时使用时重试不生效。

midscene --files './scripts/*.yaml' --retry 2

--share-browser-context

多个 Web 脚本之间共享同一个浏览器上下文(包括 Cookies、localStorage 等),避免每个脚本都重新登录:

midscene --files ./page1.yaml ./page2.yaml --share-browser-context

--headed / --keep-window

# 显示浏览器界面(默认 headless)
midscene ./test.yaml --headed

# 执行完成后保持浏览器窗口不关闭(自动开启 headed)
midscene ./test.yaml --keep-window

--setup <file>
指定一个前置脚本,在主脚本之前执行。前置脚本与主脚本共享浏览器上下文(需配合 --share-browser-context),常用于统一登录:

midscene --setup ./login.yaml --files ./search.yaml ./checkout.yaml --share-browser-context

“如果前置脚本执行失败,整个批次会中止,主脚本标记为"未执行”。”

覆盖 Web 参数

# 设置自定义 User-Agent
midscene ./test.yaml --web.userAgent "Mozilla/5.0 ..."

# 设置视口大小
midscene ./test.yaml --web.viewportWidth 1920 --web.viewportHeight 1080

环境变量相关

# 允许 .env 覆盖系统环境变量
midscene ./test.yaml --dotenv-override

# 查看 dotenv 加载日志
midscene ./test.yaml --dotenv-debug

1.6通过参数配置文件管理参数

当命令行参数越来越多时,可以把它们写入一个 YAML 配置文件,通过 --config 引用:

config.yaml:

files:
  - './scripts/login.yaml'
  - './scripts/search.yaml'
  - './scripts/checkout.yaml'

concurrent: 3
continueOnError: true
retry: 2
midscene --config ./config.yaml

“命令行参数优先级高于配置文件中的同名参数,这意味着你可以用命令行临时覆盖配置文件的某些设置。”

1.7 前置任务 + 并行执行实战

这是一套非常实用的组合:先用 --setup 完成统一登录,然后用 --concurrent 并行执行多个互不依赖的脚本:

parallel-config.yaml

setup: ./scripts/login.yaml

files:
  - ./scripts/search.yaml
  - ./scripts/profile.yaml
  - ./scripts/settings.yaml

shareBrowserContext: true
concurrent: 3
midscene --config ./parallel-config.yaml

执行流程:先执行 login.yaml 完成登录 → 登录态通过共享上下文传递给后续脚本 → 3 个脚本并行执行,互不干扰。

1.8高级连接模式

CDP 连接模式
通过 Chrome DevTools Protocol 连接到已有的浏览器实例,而不是启动新浏览器:

web:
  url: https://www.bing.com
  cdpEndpoint: ws://localhost:9222/devtools/browser

tasks:
  - name: 搜索天气
    flow:
      - ai: 搜索 "今日天气"
      - aiAssert: 显示了天气信息

CDP 模式的核心优势:

  • 使用已有的浏览器登录态,无需重复登录
  • Midscene 断开后不会关闭浏览器,可以手动继续操作
  • 适合调试和与已有工作流衔接

获取 CDP 地址的常见方式:

  • 启动 Chrome 时加 --remote-debugging-port=9222
  • 使用 BrowserBase / Browserless 等云端浏览器服务
  • Docker 容器中的 Chrome 实例

桥接模式(Bridge Mode)
通过安装 Chrome 扩展来驱动你日常使用的桌面浏览器,直接复用已有的 Cookies、插件和登录状态:

web:
  url: https://www.bing.com
  bridgeMode: newTabWithUrl   # 在当前浏览器中新建标签页

tasks:
  - name: 搜索天气
    flow:
      - ai: 搜索 "今日天气"
      - aiAssert: 显示了天气信息


bridgeMode 的两种取值:

“桥接模式需要先在 Chrome 中安装 Midscene 扩展,具体步骤参考官方文档。”

二、YAML 格式的工作流


上一章我们讲了"怎么运行",这一章我们来深入讲解"怎么写"——YAML 脚本的格式规范和所有可用指令。

2.1脚本文件结构

一个完整的 YAML 脚本包含三个主要部分:

┌──────────────────────────────────────┐
│  agent(可选)                        │
│  ├─ 报告配置                          │
│  ├─ AI 行为参数                       │
│  └─ 缓存策略                          │
├──────────────────────────────────────┤
│  平台配置(web / android / ios 等)    │
│  ├─ 目标 URL / 设备 ID                │
│  ├─ 视口大小                          │
│  └─ 连接方式                          │
├──────────────────────────────────────┤
│  tasks(任务列表)                     │
│  ├─ task 1                            │
│  │   └─ flow                          │
│  │       ├─ ai: ...                   │
│  │       ├─ sleep: ...                │
│  │       └─ aiAssert: ...             │
│  ├─ task 2                            │
│  └─ task 3                            │
└──────────────────────────────────────┘

2.2Agent配置部分(可选)

agent 部分用于控制报告生成、AI 行为参数和缓存策略,所有字段均可选:

agent:
  testId: "checkout-test"               # 测试标识符,用于报告和缓存识别
  groupName: "E2E 回归测试"              # 报告组名称
  groupDescription: "完整的购物流程测试"  # 报告组描述
  generateReport: true                  # 是否生成 HTML 报告,默认 true
  autoPrintReportMsg: true              # 是否自动打印报告路径,默认 true
  reportFileName: "checkout-report"      # 自定义报告文件名

  replanningCycleLimit: 30              # AI 最大重规划循环次数,默认 20
  aiActContext: >-                      # 调用 ai 时发送给 AI 的背景知识
    如果出现弹窗,点击"同意"按钮。
    如果出现登录页面,点击"跳过"。

  cache:
    id: "checkout-cache"                # 缓存唯一标识
    strategy: "read-write"              # read-only / read-write / write-only

aiActContext 特别实用——你可以在这里描述页面上常见的干扰项(弹窗、引导、Cookie 提示等),AI 会在每次操作时自动处理它们,而无需在每个 step 中重复描述。

2.3平台配置

web配置(web)

web:
  url: https://www.example.com           # 必填:目标 URL
  viewportWidth: 1440                    # 视口宽度,默认 1440
  viewportHeight: 800                    # 视口高度,默认 800
  deviceScaleFactor: 2                   # 设备像素比(Retina 屏幕建议设置)
  userAgent: "custom-ua-string"          # 自定义 UA
  cookie: ./cookies.json                 # JSON 格式 Cookie 文件路径
  acceptInsecureCerts: true              # 忽略 HTTPS 证书错误

  # 网络空闲等待策略
  waitForNetworkIdle:
    timeout: 2000                         # 等待超时,默认 2000ms
    continueOnNetworkIdleError: true      # 超时后是否继续,默认 true

  # 输出配置
  output: ./results/output.json          # aiQuery/aiAssert 结果输出路径

  # 连接模式(三选一)
  # cdpEndpoint: ws://localhost:9222/devtools/browser  # CDP 模式
  # bridgeMode: newTabWithUrl                          # 桥接模式

  # 其他
  forceSameTabNavigation: true           # target="_blank" 链接在当前页打开
  chromeArgs:                            # 自定义 Chrome 启动参数
    - --disable-gpu
    - --no-sandbox

2.4任务与 Flow 结构

每个 task 的核心结构如下:

tasks:
  - name: 任务名称
    continueOnError: false              # 可选,失败后是否继续下一个 task
    flow:
      - <操作类型>: <操作参数>
      - <操作类型>: <操作参数>
      # ...

2.5完整 Flow 指令速查

Midscene 的 YAML 模式支持 20+ 种 flow 指令,按功能分为以下五类:

类别一:自动规划(Auto Planning)
这些指令使用 AI 自动规划执行路径,最灵活也最常用。

flow:
  # AI 自动规划
  - ai: 在搜索框中输入 "无线耳机",然后点击搜索

  # sleep 等待
  - sleep: 2000

  # 执行 JavaScript
  - javascript: |
      document.querySelector('.cookie-banner')?.remove();
    name: remove_cookie_banner

  # 记录到报告
  - recordToReport: 搜索结果截图
    content: 搜索 "无线耳机" 后的页面状态

“ai 和 aiAct 完全等价,ai 是 aiAct 的简写。”

类别二:即时操作(Instant Actions)
这些指令对指定元素执行单一动作,比 ai 更精准、更快。

flow:
  # 点击
  - aiTap: 搜索按钮
  - aiTap: 登录按钮
    deepLocate: true                   # 开启深度定位

  # 悬停
  - aiHover: 用户头像

  # 输入
  - aiInput: 用户名输入框
    value: admin@example.com

  # 按键
  - aiKeyboardPress: 搜索框
    keyName: Enter

  # 滚动
  - aiScroll: 商品列表
    scrollType: scrollToBottom          # 滚到底部
  - aiScroll: 商品列表
    scrollType: singleAction
    direction: down
    distance: 500                       # 向下滚动 500px

类别三:数据提取(Data Extraction)

flow:
  - aiQuery: 提取搜索结果中所有商品的标题和价格
    name: product_list

  - aiString: 读取页面顶部的标题文字
    name: page_title

  - aiNumber: 购物车中的商品数量是多少?
    name: cart_count

  - aiBoolean: 页面上是否显示了"已售罄"标志?
    name: is_sold_out

类别四:等待与断言(Wait & Assert)

flow:
  # 等待结果加载
  - aiWaitFor: 商品列表中出现至少 5 个商品
    timeout: 10000

  # 断言
  - aiAssert: 页面顶部显示 "搜索结果"
    errorMessage: "搜索结果标题未显示"

  - aiAssert: 购物车图标右上角显示数字 1
    name: cart_assertion

类别五:平台特定指令

flow:
  # 启动应用
  - launch: com.android.settings

  # 执行 ADB 命令(不写 adb shell 前缀)
  - runAdbShell: 'pm clear com.example.app'

  # 终止应用
  - terminate: com.android.settings

  # Gherkin 场景
  - runGherkinScenario: |
      Scenario: 添加待办事项
        Given 待办事项页面已经打开
        When 我添加一条名为"买牛奶"的待办事项
        Then 待办事项列表中应该包含"买牛奶"

2.6 在 YAML 中使用环境变量

你可以在 YAML 脚本中通过 ${variable-name} 语法引用环境变量,Midscene 会在执行前完成替换:

web:
  url: https://${DOMAIN}/home

tasks:
  - name: 搜索商品
    flow:
      - ai: 在搜索框中输入 ${SEARCH_KEYWORD}
      - aiTap: 搜索按钮
      - aiAssert: 结果中包含 ${EXPECTED_RESULT}
DOMAIN=www.example.com SEARCH_KEYWORD=耳机 EXPECTED_RESULT=索尼 \
  midscene ./search.yaml

这在 CI/CD 中非常实用——同一个 YAML 脚本可以通过不同的环境变量驱动不同的测试数据。

这在 CI/CD 中非常实用——同一个 YAML 脚本可以通过不同的环境变量驱动不同的测试数据。

2.7 文件上传
仅 Web 环境支持。在 aiTap 中添加 fileChooserAccept 即可:

flow:
  # 上传单个文件
  - aiTap: 选择文件按钮
    fileChooserAccept: ./fixtures/report.pdf

  # 上传多个文件
  - aiTap: 上传图片按钮
    fileChooserAccept:
      - ./fixtures/image1.jpg
      - ./fixtures/image2.png

2.8 图像提示

在提示词中附加参考图像,帮助 AI 精确定位目标元素:

flow:
  # 在点击操作中使用图像参考
  - aiTap:
      locate:
        prompt: 点击包含该图标的按钮
        images:
          - name: GitHub 标志
            url: https://github.githubassets.com/assets/GitHub-Mark-ea2971cee799.png
        convertHttpImage2Base64: true

  # 在断言中使用图像参考
  - aiAssert:
      prompt: 页面上显示了该产品图片
      images:
        - name: 目标产品
          url: https://example.com/product-image.png
      convertHttpImage2Base64: true

convertHttpImage2Base64: true 会将网络图片转为 base64 传给 AI 模型(确保模型能访问到图片)。

2.9 完整示例:电商搜索流程

agent:
  testId: "ecommerce-search"
  groupName: "电商搜索回归测试"
  aiActContext: "如果出现优惠弹窗,点击关闭。如果出现 Cookie 提示,点击同意。"

web:
  url: https://shop.example.com
  viewportWidth: 1440
  viewportHeight: 900

tasks:
  - name: 搜索商品并加入购物车
    flow:
      # 等待首页加载
      - aiWaitFor: 搜索框已经显示
        timeout: 10000

      # 搜索
      - aiInput: 搜索框
        value: 无线降噪耳机
      - aiKeyboardPress: 搜索框
        keyName: Enter
      - sleep: 2000

      # 验证搜索结果
      - aiAssert: 搜索结果列表中存在至少一个商品
        errorMessage: "搜索结果为空"

      # 提取数据
      - aiQuery: 提取前5个商品的名称和价格
        name: top_5_products

      # 点击第一个商品
      - aiTap: 第一个搜索结果
      - aiWaitFor: 商品详情页加载完成
        timeout: 5000

      # 加入购物车
      - aiTap: 加入购物车按钮
      - aiAssert: 页面显示"已加入购物车"
        name: add_to_cart_success

      # 截图留存
      - recordToReport: 购物车确认页
        content: 商品成功加入购物车后的页面

三、总结

YAML 脚本模式是 Midscene.js 提供的一种低代码自动化方案,它的核心价值在于:

  1. 零代码门槛:用自然语言 + YAML 描述自动化流程,无需编写任何 JavaScript/TypeScript 代码
  2. 一键执行:通过 midscene CLI 命令直接运行,自动生成可视化报告
  3. 全平台覆盖:支持 Web、Android、iOS、HarmonyOS、桌面(Mac/Windows/Linux)多平台
  4. 丰富的命令体系:从自动规划(ai)到即时动作(aiTap/aiInput),从数据提取(aiQuery)到断言验证(aiAssert),覆盖 UI 自动化的完整生命周期
  5. 灵活的工程化能力:支持环境变量插值、批量并发执行、配置文件管理、CDP/桥接模式等

一句话建议:能用一个 .yaml 文件搞定的简单流程,就用 YAML 模式;需要复杂逻辑、条件判断、循环操作的场景,用 Playwright 测试模式。

Logo

一站式 AI 云服务平台

更多推荐