配置测试项目
midscene.config.ts 是 Midscene Test 的项目配置文件。你可以在其中配置浏览器或设备的初始化方式、注册用例可调用的 Node,并设置并发数、超时等运行参数。本文介绍配置文件结构、Agent 与平台接入、多执行项目管理,以及编程式调用。
配置文件结构
使用 defineTestProject() 定义并导出项目配置。执行项目负责选择用例并提供运行环境。
Midscene Test 支持以下配置文件:
Midscene Test 默认会加载 midscene.config.ts 或 midscene.config.mjs。如果两个文件同时存在,Midscene Test 会报告冲突,而不是静默选择其中一个;此时可以通过 --config <路径> 明确指定要使用的文件。
在 setup 中准备项目共享资源,在 fileSetup 中准备每份文件独立使用的资源,并通过 nodes 注册对应 Agent 的 Node。
下面先以单个执行项目为例介绍配置方法。如果需要管理多个执行项目,或为不同项目注册各自的 Node,请参阅配置多个执行项目。
配置运行环境
完整示例:Playwright
下面是只使用 setup 的串行配置:同一执行项目中的所有文件共用一个页面。需要每份文件使用独立环境时,添加 fileSetup,不必先开启并发。
如果要在已有工程中手动接入,请先安装 @midscene/test、@midscene/web 和 playwright(pnpm add -D @midscene/test @midscene/web playwright),再执行 pnpm exec playwright install chromium 安装浏览器。运行测试前,还需按模型配置设置 API Key 等环境变量。
这个配置中,各部分的关系如下:
setup创建浏览器和页面,并通过onTeardown()注册清理函数。context保存运行时资源。Node 通过getAgent获取 Agent;首次调用时创建实例并保存在context.agent中,供后续调用复用。Playwright Node 使用该 Agent 的页面。nodes注册通用 AI 操作和 Playwright 操作,供 YAML 用例调用。projects声明名为chromium的执行项目,将setup与cases/下的 YAML 文件关联起来。
接下来可以编写 YAML 测试用例并运行测试。下面进一步说明这些资源如何共享和清理。
使用 setup 创建和清理共享资源
defineProjectSetup() 定义项目的准备工作,通过 setup 字段配置。测试运 行时,每个执行项目调用一次其中的 setup()。上面的示例返回浏览器和页面,供该项目的 Node 共用。
需要文件隔离时,用 defineFileSetup() 定义每份文件的准备工作,通过 fileSetup 字段配置。它接收项目 setup 的返回值,再为当前文件创建资源。两者的关系和示例见用 fileSetup 隔离资源。
共享资源不会在每个用例开始时自动重建。需要重置页面、Cookie 或业务状态时,可以通过 YAML 的生命周期钩子调用相应 Node。自定义 Node 如何读写共享数据,见跨 Node 共享上下文。
创建浏览器、Agent 等资源后,应立即通过 onTeardown() 注册对应的清理函数。即使 setup 或测试执行失败,框架也会在项目结束时尝试执行已注册的清理函数。清理顺序与注册顺序相反:在上面的 Playwright 示例中,先销毁 Agent,再关闭浏览器。
这里的 onTeardown() 在项目结束时执行。在 Node 内部注册的清理函数有独立的执行范围。
项目生命周期
setup、fileSetup 与 beforeAll
三者按 setup → fileSetup → beforeAll → 用例 的顺序执行,未配置的部分会跳过。
正常执行两份 YAML 时,setup 执行一次,fileSetup 和 beforeAll 各执行两次;并发数不改变执行次数。
fileSetup 配置一次即可用于所有文件;beforeAll 由各文件声明。自定义 Node 也能在 beforeAll 中创建资源,但框架不会因此创建独立的文件 context。
项目、文件与用例的生命周期
通过 CLI 或 runTestProject() 运行测试时,每个执行项目都有独立的生命周期。下面展示一个包含两个 YAML 文件的项目在顺序执行时的正常流程;未声明的 YAML 钩子会跳过:
beforeAll 和 afterAll 每份 YAML 各执行一次;beforeEach 和 afterEach 包围每个用例的每次尝试。配置了文件并发后,不同文件可以同时推进,文件内部仍按图中顺序执行。
用例重试沿用原来的文件环境,只重复 beforeEach → steps → afterEach → 本次执行的 Node 清理。项目 setup、fileSetup 和 beforeAll 都不会重跑。重试条件和失败后的跳过规则见失败时如何执行。
onTeardown() 的清理范围取决于注册位置:
每个范围内的清理函数都按注册顺序的逆序执行。一个函数抛错后仍会尝试后续函数;函数尚未结束时,后续清理等待它结束。Node 清理的实现方式见资源的生命周期与清理。
context 的共享范围
Node 收到的 context 由配置决定:
同一共享范围内,Node 收到的是同一个对象。写入 context.orderId 后,后续用例也可能读到它。框架不会在用例切换或重试时重置 context、页面或登录状态;用例需要的初始状态应在 beforeEach 中恢复。
在 setup() 函数内部创建资源和返回对象。多个项目或文件即使引用同一个定义,也会分别调用函数;如果返回模块顶层的同一个可变对象,仍会共享状态。数据传递示例见跨 Node 共享上下文。
注册官方 Node
通用 AI 操作与 Agent 接入
Midscene Test 内核不隐式注册 Node。midscene-test create 生成的配置会调用 @midscene/test/midscene 导出的 createMidsceneNodes(),注册所选平台的官方 Node。手写配置时,需要将该函数返回的 Node 定义显式放入顶层 nodes 或 projects[].nodes。
createMidsceneNodes() 返回两部分能力:agentClass.getTestRunnerNodeDefinitions() 声明的通用 Agent Node 和平台 Node,以及 Test 提供的 wait Node。通用能力包含 AI 操作、断言与信息提取、界面定位、报告记录等;平台 Agent 再追加浏览器或设备操作。完整名称和输入字段不在网站中维护重复清单,请以当前项目生成的 Node 说明书 为准。
调用 createMidsceneNodes() 时,通过 agentClass 指定 Agent 类,通过 getAgent 回调提供运行时使用的 Agent 实例:
createMidsceneNodes() 不会直接修改全局注册表;只有把返回数组加入项目配置后,这些 Node 才会生效。agentClass 是 Agent Node 定义的唯一来源,getAgent 则说明执行期间如何从当前 context 取得 Agent 实例。如果该类没有提供 getTestRunnerNodeDefinitions(),工厂会在注册阶段抛出异常。传入 PlaywrightAgent、PlaywrightPageAgent、PlaywrightBrowserAgent、PuppeteerAgent 、PuppeteerPageAgent、PuppeteerBrowserAgent、AndroidAgent、IOSAgent 或 HarmonyAgent 时,会同时获得通用 Node 定义和对应的平台 Node 定义。基础 Agent 和 ComputerAgent 仅提供通用 Agent Node。
Android/iOS 的注册示例见配置多个执行项目。
在 Android、iOS 等设备平台接入 Agent 时,需注意资源的所有权。每个 Device 实例只归属于一个 Agent,Agent.destroy() 也会销毁对应 Device。每个执行项目应创建独立的资源,不要在 Agent 销毁后复用它的 Device。
各平台都通过 createMidsceneNodes() 注册,使用 agentClass 声明平台,通过 getAgent 获取实例。项目 context 的字段名由你自行定义。
注册后,可在 YAML 中调用这些 Node。参数写法见其他 Node 的调用模式,具体字段以项目生成的 Node 说明书为准。
Playwright
通过 createMidsceneNodes({ agentClass: PlaywrightAgent, getAgent }) 会自动注册 gotoUrl、setCookies、clearCookies 和 setViewportSize。使用这些 Node 前,需要在项目中安装 playwright。它是 @midscene/web 的同级依赖(peer dependency):
Cookie 默认从 process.env 读取。只有需要自定义 Cookie 来源时,才在创建 Agent 时传入 testRunner 选项,例如 getEnv、getCookieProfile 或 resolveStorageStatePath。这些回调中的 context 是当前 Agent。

