使用 Midscene.js 和 Playwright 进行 AI 驱动的 E2E 测试
无需编写选择器的 E2E 测试。在本文中,我们将尝试使用 Midscene.js 通过自然语言命令控制 UI,结合 Playwright,这是流行的自动化浏览器测试框架。
什么是 Midscene.js?
Midscene.js 是一个 JavaScript SDK,它使用 LLM 模型(如 GPT-4o 或 Qwen)来解释我们的命令,例如:
"输入
art toy并搜索" "提取所有产品名称和价格"
并将它们转换为实际的浏览器交互,而无需编写任何 DOM/选择器代码。
与 Playwright 集成
对于那些想查看完整 playwright 配置(包括 e2e 代码本身)的人,您可以查看 midscenejs 创建的示例项目 https://github.com/web-infra-dev/midscene-example/blob/main/playwright-demo https://midscenejs.com/integrate-with-playwright.html
在这里,我们将尝试 在 popmart 上搜索 chaka
./e2e/popmart-search.ts
import { expect } from "@playwright/test";
import { test } from "./fixture";
test.beforeEach(async ({ page, aiTap }) => {
  page.setViewportSize({ width: 1280, height: 768 });
  await page.goto("https://www.popmart.com/th");
  await page.waitForLoadState("load");
  await aiTap('click the "ยอมรับ" (accept) button for privacy policy at the bottom of the page');
});
test("search chaka on popmart", async ({
  ai,
  aiQuery,
  aiAssert,
  aiWaitFor,
  aiNumber,
  aiBoolean,
  aiString,
  aiLocate,
}) => {
  // 👀 type keywords, perform a search
  await ai('type "chaka" in search box located in the top appbar, hit Enter');
  // 👀 wait for the loading
  await aiWaitFor("there is at least one item item on page");
  // 👀 find the items
  const items = await aiQuery(
    "{itemTitle: string, price: Number}[], find item in list and price"
  );
  console.log("items", items);
  expect(items?.length).toBeGreaterThan(0);
});
逐步说明
- 转到 https://www.popmart.com/th 并等待完成
 - 我们将使用 
aiTap点击 cookie 部分中的接受按钮 

使用 midscene 的另一个优势是它可以直观地报告每个操作
ai('type "chaka" in search box located in the top appbar, hit Enter')告诉 AI 在顶部应用栏找到搜索框,输入 chaka 并按回车
如果您尝试在实际网站上点击,您会看到它不仅仅是点击并在该框中输入,而是 UI 显示类似抽屉的元素,它也可以处理这个
4.await aiWaitFor("there is at least one item item on page")
等待直到项目出现
aiQuery我们告诉它帮助查询项目和价格{itemTitle: string, price: Number}[], find item in list and price
期望项目存在。实际上,我们还可以添加一个条件,即项目必须与我们搜索的关键字相关(在这种情况下是 Chaka)
但我们应该注意,这是从可视化的角度作为图像,这意味着它只看到屏幕上显示的内容。

items [
  { itemTitle: 'CHAKA Candle Whisper Series Figures', price: 380 },
  { itemTitle: 'CHAKA Candle Whisper Series Figures', price: 380 },
  {
    itemTitle: 'MEGA SPACE MOLLY 400% Sanrio Characters Series',
    price: 6290
  }
]
报告
运行后,我们可以查看每个操作的报告,它显示是否是 AI 操作,使用了多少 tokens,以及花费了多长时间。

缓存
我相信许多人会问"如果每次都要调用 AI,这不会很贵和很慢吗?"
Midscene 支持缓存规划步骤和 DOM XPath 以减少对 AI 模型的调用。第一次测试运行后,它将创建缓存作为 .yaml
midscene_run/cache/popmart.spec.ts(search-chaka-on-popmart).cache
midsceneVersion: 0.17.0
cacheId: popmart.spec.ts(search-chaka-on-popmart)
caches:
  - type: locate
    prompt: >-
      click the "ยอมรับ" (accept) button for privacy policy at the bottom of the
      page
    xpaths:
      - //*[@id="__next"]/div[1]/div[1]/div[4]/div[1]/div[2]/text()
  - type: locate
    prompt: The search box in the top appbar
    xpaths:
      - >-
        //*[@id="__next"]/div[1]/div[1]/div[1]/div[1]/div[2]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/img[1]
  - type: plan
    prompt: type "chaka" in search box located in the top appbar, hit Enter
    yamlWorkflow: |
      tasks:
        - name: type "chaka" in search box located in the top appbar, hit Enter
          flow:
            - aiInput: chaka
              locate: The search box located in the top appbar
            - aiKeyboardPress: Enter
  - type: locate
    prompt: The search box located in the top appbar
    xpaths:
      - >-
        //*[@id="__next"]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[1]/text()
这是运行 popmart 搜索测试后的示例。您会看到它已经创建了规划和 xpaths。
所以下次如果我们使用缓存运行,它将使用这些命令而不是调用 AI。
除了
aiBoolean、aiQuery、aiAssert不会被缓存,因为它们是查询,而不是操作。
AI 模型
由于 midscenejs 是一个独立于任何云提供商或模型的开源项目,我们可以选择公开或私下部署。
使用 AI 进行 E2E 测试相比传统测试的优势
- 理解 UI 而不依赖于 DOM 选择器
 
- 如果 UI 更改元素类型(例如 
<button>→<a>),传统测试脚本将中断 - 但 AI 会查看 UI 上下文,如文本、颜色、位置 或者有时期望它是一个圆形吗?它是红色的吗?
 
- 易于与非开发团队成员沟通
 
- PM、设计师可以阅读测试
 - 或者自己编写基本提示而无需了解 JavaScript
 - 例如"打开设置页面并检查是否有深色模式的切换"
 
- 
适合测试业务逻辑/高级场景
 - 
更容易为动态 UI 编写测试
 
- 例如"点击确认,右上角应该出现成功对话框"
 - 传统测试可能需要许多分支,但 AI 更好地理解上下文
 
但是,我们仍然不应该将所有 AI 操作合并到一个命令中。我们应该仍然清楚地分离操作,因为这是一个测试,我们不希望在测试系统中运行时每次都有非确定性行为 https://midscenejs.com/blog-programming-practice-using-structured-api.html
结论
在我看来,使用基于 AI 的测试就像有一个"理解 UI 的助手"来帮助编写测试——它不能替代一切,我们也需要理解这一点。但它有助于解决实际用户交互流中的问题。我们可以从可视化的角度思考它,比如当用户这样做时,屏幕上应该发生这种情况。有时捕获元素可能非常困难,但从实际用户的角度来看,它可能确实非常简单。