• 简体中文
  • 迁移到 Midscene Test

    旧版 YAML 与原生 Midscene Test 共用底层执行内核和报告页面,但用户入口相互独立。midscene 负责旧版 tasks/flow 文件、YAML 批配置和旧 CLI 参数;midscene-test 负责原生 cases/steps 文件、TypeScript 或 JavaScript 项目配置、生命周期和 Node。

    什么是“旧版 YAML”

    本文所说的“旧版 YAML”,特指 @midscene/cli 的 YAML 自动化协议,而不是所有 YAML 文件。它通常具有以下特征:工作流顶层是 tasks,用 tasks[].flow 编排动作;平台、Agent 和输出配置直接写在工作流 YAML 中;批量运行使用包含 filessetupconcurrentretry 等字段的 YAML 配置;执行入口是 midscene。顶层使用 cases/steps 和生命周期钩子、由 midscene-test 执行的文件属于原生 Test,不属于旧版 YAML。

    旧链路只做兼容维护和必要的问题修复,不再新增语法、能力、配置项或 CLI 参数。新项目、新增用例和后续能力建设应采用原生 Midscene Test;现有旧项目可以继续运行,并按业务节奏逐步迁移。

    本文把迁移分为两条路径:

    • 原地升级:旧用例、批配置、目录结构和 midscene 命令均保持不变,先获得共享执行内核和新报告,不改变输入契约。
    • 原生迁移:按完整文件把旧字段改写为 Test 的文档、Case 和 Step,用项目配置替换 YAML 批配置,再把这些文件切换到 midscene-test

    旧版字段的完整参考仍保留在 YAML 脚本运行器YAML 格式的工作流中,供现有项目维护和迁移时查阅。

    路径一:原地升级旧链路

    如果项目已经安装 @midscene/cli,升级后继续使用原命令。midscene 会保留旧输入语义,通过共享内核执行,并生成新的报告页面:

    pnpm exec midscene ./flow.yaml
    pnpm exec midscene --config ./batch.yaml

    原来的平台配置、agent、环境变量插值、task continuation、整文件重试、输出文件和 summary 仍按旧语义处理;报告切换为新 Test 页面,旧 HTML 文件无需转换,重新运行即可生成。旧 agent.generateReport: false 仍生效。

    --files--setup--concurrent--retry--continue-on-error--summary--headed--keep-window--share-browser-context--dotenv-override--dotenv-debug--<target>.<field>--no-<target>.<field> 继续由 midscene 接受。它们不是 midscene-test 参数,也不出现在 Test 主帮助中。

    命令与文件边界
    • midscene 只接受旧版 tasks/flow 工作流文件和 YAML 批配置。
    • midscene-test 只接受原生 cases/steps 工作流文件和 TypeScript 或 JavaScript 项目配置。
    • 单个 YAML 文件不能同时声明旧版 tasks 与原生 cases 或生命周期钩子。
    • 同一次命令不能选择两种格式。渐进迁移时,应放在不同目录或文件选择范围,并分别执行两条命令。
    • --project--result-dirmidscene-test nodes 只属于原生 Test;旧调度和平台参数继续属于 midscene

    两条命令都会在创建浏览器、设备或 Agent 资源前检查边界。遇到错误格式时,会列出文件并提示正确命令,不会静默转发。

    路径二:迁移为原生 Test 项目

    建议按下面的顺序迁移,保证每一步都可以独立运行和对比结果:

    1. 先使用 midscene 运行原项目,保存退出状态、summary 和新报告作为基线。
    2. 使用 pnpm dlx @midscene/test create 创建对应平台的 Test 项目,从生成的 midscene.config.ts 和 setup 开始配置运行环境。
    3. 将旧批配置映射到执行项目,把平台、Agent 和资源创建移入 setup。
    4. 每次完整地把一个 tasks/flow 文件改为 cases/steps,移入原生文件选择范围,再用 midscene-test 运行;未转换文件继续交给 midscene
    5. 运行 pnpm exec midscene-test nodes --project <name> 生成当前项目的 Node 说明书,根据说明书校验动作名称、参数和字符串简写。
    6. 全部转换后,移除旧批配置、旧命令和旧链路专用参数。

    用例结构映射

    旧版:

    web:
      url: https://example.com
    
    tasks:
      - name: 搜索商品
        continueOnError: true
        flow:
          - ai: 搜索马克杯
          - aiAssert: 搜索结果中包含马克杯
            errorMessage: 未找到目标商品

    原生 Test:

    beforeEach:
      - gotoUrl: https://example.com
    
    cases:
      - name: 搜索商品
        steps:
          - aiAct: 搜索马克杯
          - aiAssert:
              prompt: 搜索结果中包含马克杯
              message: 未找到目标商品
    旧版字段原生 Test 字段或机制说明
    taskscases一个旧 task 对应一个 Case。
    tasks[].namecases[].name名称直接保留。
    tasks[].flowcases[].steps一个 flow item 对应一个 Step。
    tasks[].continueOnError: true原生 Case 的默认继续行为midscene 保留旧 task continuation;原生 Test 默认继续下一个 Case。
    未设置 continueOnError旧链路的失败策略midscene 停止当前旧文件。原生没有 onFailure 参数;公共前置条件放在 beforeAll,有依赖关系的步骤放在同一个 Case。
    顶层平台字段中的初始页面或应用setup 加生命周期 Node资源创建放在 setup;每个 Case 都应重新进入初始状态时,使用 beforeEachgotoUrllaunch 等 Node。
    旧版没有对应字段beforeAllbeforeEachafterEachafterAll原生 Test 提供的文件和 Case 生命周期。
    旧版没有对应字段cases[].tags用于按项目选择 Case。

    保留旧文件即可保留旧失败策略;手写原生 Case 则采用原生语义,不保证调度行为一一等价。Step 的 $: { continue-on-error: true } 只让同阶段后续 Step 继续,不控制旧 task 之间的调度,也不会把失败 Case 改为成功。

    flow 动作映射

    旧 runtime 会继续接受左侧字段,并在内部适配到共享内核;这种内部转换不是原生 Test 的输入契约。迁移文件时应改写为右侧的原生形式,并以 midscene-node-reference.md 中当前项目实际注册的 Node 为准。

    旧版 flow 字段原生 Test Node / 输入迁移说明
    aiaiActionaiActinstructionaiAct.prompt统一使用 aiAct。其余选项放入 options
    aiAssertaiAssert.prompterrorMessage 改为 message,其余提取选项放入 options
    aiQueryaiNumberaiStringaiBooleanaiAskaiLocate同名 Node 的 prompt图片与提取选项按 Node 说明书放入 promptoptions
    aiWaitForaiWaitFor.prompttimeout 对应 Node 输入中的 options.timeoutMs
    aiTapaiTap.prompt旧的 locate、图片和定位选项整理到 promptoptions
    aiScrollaiScroll定位描述作为 prompt,滚动参数放入 options
    aiInputaiInput.valueaiInput.prompt输入值放入 value,定位描述放入 prompt
    aiKeyboardPressaiKeyboardPress.keyName 和可选 prompt具体输入以项目 Node 说明书为准。
    sleepsleep.ms例如 sleep: 1000 改为 sleep: { ms: 1000 }。新用例也可以使用通用 wait Node。
    javascriptjavascript.script返回值会记录在 Step 结果中。
    recordToReportlogScreenshotrecordToReport标题映射到 titlecontent 放入 options.content
    runGherkinScenariorunGherkinScenario.scenario旧链路会关闭该动作的缓存。
    runAdbShellrunAdbShell命令映射到 command,旧 timeout 保留为 Node 输入。
    Finalize旧链路专用规划标记旧 runtime 仍接受;原生 Case 中省略,不作为公开 Node。
    其他平台动作和自定义动作已注册的同名 Node,或通用 action Node先运行 midscene-test nodes,根据目标平台的 Node 说明书改写参数。
    flow item 的 nameNode 的结构化结果midscene 仍按旧名称写入输出;原生 Test 不提供跨 Step 的命名结果表达式,数据共享应使用自定义 Node 和项目 context

    具体示例:迁移一个提交订单 Case

    下面的旧用例填写收货人、等待提交按钮可用、提交订单并记录结果。它同时使用了 task 失败策略、动作别名、定位输入、动作超时、断言错误消息、固定等待和报告记录:

    web:
      url: https://shop.example.com/checkout
    
    tasks:
      - name: 提交订单
        continueOnError: true
        flow:
          - aiInput: Alice
            locate: 收货人姓名输入框
          - aiWaitFor: 提交订单按钮已启用
            timeout: 10000
          - ai: 点击提交订单按钮
          - aiAssert: 页面显示订单提交成功
            errorMessage: 提交后没有出现成功提示
          - sleep: 500
          - recordToReport: 订单提交结果
            content: 已完成下单流程

    迁移成原生 Test 后,同一个 Case 可以写成:

    beforeEach:
      - gotoUrl: https://shop.example.com/checkout
    
    cases:
      - name: 提交订单
        steps:
          - aiInput:
              prompt: 收货人姓名输入框
              value: Alice
          - aiWaitFor:
              prompt: 提交订单按钮已启用
              options:
                timeoutMs: 10000
          - aiAct: 点击提交订单按钮
          - aiAssert:
              prompt: 页面显示订单提交成功
              message: 提交后没有出现成功提示
          - wait:
              duration: 500
              unit: ms
          - recordToReport:
              title: 订单提交结果
              options:
                content: 已完成下单流程

    这里发生了几类转换:

    1. web.url 不再和用例内容混在一起。浏览器由项目的 setup 创建,需要在每个 Case 开始时进入结算页,因此 URL 放到 beforeEachgotoUrl
    2. task 变成 Case;原生 Test 默认在 Case 失败后继续,因此这个例子无需额外的继续参数。
    3. aiInput 的值和定位描述从同级旧字段拆成 Node 的 valueprompt
    4. aiWaitFor.timeout 是动作自身的等待上限,所以放入 options.timeoutMs。如果要限制整个 Step,应另用 $: { timeout: 10000 }
    5. ai 统一为 aiActaiAssert.errorMessage 改为 aiAssert.message
    6. 固定等待改用原生通用 wait Node;报告标题与正文分别放入 recordToReport.titleoptions.content

    这个例子只调整输入结构,没有改变业务执行顺序。实际迁移时应先运行 pnpm exec midscene-test nodes --project <name>,生成当前项目的 midscene-node-reference.md。以这份 Node 说明书为准确认 gotoUrlaiInputaiWaitFor 等 Node 是否可用以及参数如何填写,不要根据其他平台的示例推测。

    脚本和 Agent 配置映射

    midscene 会继续读取旧 YAML 顶层配置。迁移为原生 Test 时,这些字段不再放在 Case YAML 中,而是进入 midscene.config.ts、setup 或 Node:

    旧版脚本字段原生 Test 配置或机制说明
    targetWeb 项目的 setup该字段已废弃;迁移时不要继续使用,按实际模式配置 Playwright、Puppeteer 或 bridge runtime。
    pagebrowserwebWeb 项目的 setup + Web Node浏览器启动、CDP、viewport、Cookie、headers 等连接配置放入 setup;进入页面、设置 Cookie 等可重复动作放入生命周期 Node。
    androidAndroid 项目的 setup + Android Node设备 ID、截图和输入策略用于创建 Device/Agent;launch 等用例动作放入 beforeEachsteps
    iosiOS 项目的 setup + iOS NodeWDA 连接和 Device/Agent 创建放入 setup;应用启动和交互使用已注册 Node。
    harmonyHarmonyOS 项目的 setup + HarmonyOS NodeHDC 连接、设备参数和应用映射放入 setup;应用与 Shell 操作使用已注册 Node。
    computerComputer 项目的 setup + Computer Nodedisplay 等设备参数放入 setup;界面操作使用已注册 Node。
    interface自定义项目的 setup + createMidsceneNodes()在 setup 中导入并创建自定义 Interface、Device 和 Agent,再把 Agent 暴露给 Node。
    agent.generateReport旧链路的报告设置旧 YAML 仍可关闭自身报告;原生 Test 始终生成统一总报告。
    agent.reportFileNameagent.testId旧链路的 Agent 产物设置查看报告时,以 CLI 输出的路径或 summary 中的报告链接为准。testId 已废弃。
    agent.groupNameagent.groupDescription项目、Case 名称和报告结构没有同名原生字段;将分组语义放入项目名称、Case 名称或 tags。
    agent.replanningCycleLimitagent.aiContextsagent.aiActContextagent.aiActionContextagent.cacheagent.screenshotShrinkFactorsetup 中的 Agent options创建 Agent 时继续传入相应选项,不再写在 Case YAML 中。
    agent.outputFormatagent.persistExecutionDumpagent.autoPrintReportMsgTest 报告或 setup 中的 Agent options优先采用 Test 的统一报告;只有仍需 Agent 自身行为时才在 setup 中保留对应选项。
    config.output,或平台字段中的 outputTest 结构化结果midscene 继续写旧输出文件;原生 Test 使用 --result-dirsummary.json 和报告。业务数据应由自定义 Node 返回或写入外部存储。
    config.unstableLogContentTest 报告与结构化结果没有同名原生字段;迁移消费方,不再依赖旧的实验性日志内容文件。
    tasks原生 Workflow Document按前文映射为 cases 和生命周期钩子。

    setup 的完整写法和各平台 Node 注册方式见配置运行环境

    批配置映射

    旧版 batch.yaml

    files:
      - flows/cases/**/*.yaml
    setup: flows/setup.yaml
    concurrent: 2
    retry: 1
    continueOnError: false
    summary: result.json
    headed: true

    原生 Test 把执行参数放在 midscene.config.ts

    import { defineTestProject } from '@midscene/test/config';
    import { nodes, setup } from './test-runtime';
    
    export default defineTestProject({
      nodes,
      projects: [
        {
          name: 'default',
          setup,
          files: {
            include: ['flows/cases/**/*.yaml'],
          },
          retry: 1,
        },
      ],
      test: {
        bail: 1,
      },
      output: {
        reportDir: './midscene_run/report',
      },
    });
    旧版批配置原生 Test 配置或机制说明
    filesprojects[].files.includemidscene 保留旧顺序和重复调用;原生选择固定去重、排序,没有 files.order 开关。
    setup旧链路前置文件;原生 setup / beforeAll旧宿主先执行 setup 文件;原生在 setup 创建资源,用生命周期 Step 表达文件前置条件,没有 setupFile 参数。
    concurrent旧链路文件调度;原生 test.maxConcurrencymidscene 保留文件并发;原生并发单位是持有独立资源的项目,不是同一项目内的文件。
    retry旧链路整文件重试;原生 projects[].retry原生只重试失败 Case;确需整文件重放时继续使用 midscene,没有 retryScope 开关。
    continueOnError: falsetest.bail: 1失败达到阈值后停止调度新的文件或 Case。已经开始的并发任务仍会完成清理。
    continueOnError: truetest.bail: 0不因失败阈值触发全局停止;midscene 另行保留旧 task continuation,原生 Case 默认继续。
    summaryTest summary.json、报告和编程式 APImidscene 仍写旧 summary;原生 Test 没有同名配置,应迁移消费方。可用 --result-dir 指定结构化结果目录。
    shareBrowserContext旧链路资源宿主;原生项目的 setup旧宿主在共享浏览器上下文上创建独立 Page/Agent;原生通过 setup 在项目内共享资源,并发项目之间持有独立资源。
    headed浏览器或设备 setup 的启动参数例如 Playwright 使用 chromium.launch({ headless: false })
    keepWindowsetup 的清理策略仅建议本地调试使用;需要由项目决定是否延迟或跳过浏览器 teardown。
    dotenvOverridedotenvDebug项目的环境变量加载方式原生读取 process.env;依赖 .env 文件时,在配置文件或启动脚本中显式加载,并在那里设置优先级和调试行为。
    webandroidiosharmonycomputerinterface项目的 setupvariables 和平台注册 Node设备连接和 Agent 创建移入 setup;可序列化的环境差异放入 variables

    这个原生示例只迁移了文件选择和 Case 重试,不保留旧前置文件、并发文件的调度方式。原生并发应拆成独立项目,并设置 test.maxConcurrency。旧链路所需的文件并发和 document setup 留在 midscene 入口之后,不成为公开 Test 配置。

    midscene 保留旧输出命名规则:显式 flow name、未命名提取结果的数字键,以及重复名称的覆盖规则均保留。

    验证迁移结果

    同一个用例先用 midscene 运行旧版本,再用 midscene-test 运行转换后的版本,至少核对:

    • 进程退出码和失败后是否继续执行。
    • 重试单位是 Case 还是整个文件。
    • 环境变量、平台连接参数和初始页面状态。
    • AI 动作输入、超时和断言失败信息。
    • 业务输出的消费方式,以及新 Test 报告中的 Step 结果。
    • 并发执行时页面、Agent、设备和测试数据是否隔离。
    • 失败、超时和 Ctrl+C 中断后,生命周期钩子与资源清理是否完成。

    迁移完成后,新增用例应使用 cases/steps。只有尚未迁移的文件继续保留 tasks/flow,避免在新代码中继续扩大兼容格式的使用范围。