Playwright:现代Web自动化测试与AI应用开发的利器

1. 项目概述:为什么是Playwright?

如果你最近在搞Web自动化测试,或者想给AI应用加个能“看”网页、能“点”按钮的“手和眼睛”,那你大概率已经听过Playwright这个名字了。这玩意儿现在火得不行,不是没有道理的。我最早接触自动化测试还是从Selenium开始,后来用过Puppeteer,直到去年一个项目里被跨域iframe和动态加载搞得焦头烂额时,同事推荐了Playwright,一试之下,真有种“相见恨晚”的感觉。

简单说,Playwright是一个由微软开源的现代Web自动化测试和浏览器自动化库。它最核心的价值,是 为现代Web应用而生 。现在的网页早就不是十年前那种静态文档了,全是SPA(单页应用)、懒加载、Shadow DOM、复杂的身份验证流程。你用老工具去测,就像拿螺丝刀去拧六角螺栓,不是不能用,但费劲,还容易滑丝。Playwright的设计哲学就是“拥抱现代Web”,它原生支持所有现代浏览器引擎(Chromium, Firefox, WebKit),提供跨浏览器、跨平台的统一API,并且从一开始就考虑到了单页应用、网络拦截、文件上传下载这些让人头疼的场景。

更关键的是,它和 AI应用开发 这个风口结合得异常紧密。你想啊,现在的大模型应用、AI Agent,很多都需要与真实的Web环境交互:自动收集数据、模拟用户操作完成任务、对网页内容进行理解和分析。Playwright稳定、可靠且功能强大的浏览器控制能力,让它成了连接AI大脑(大模型)和Web世界(操作界面)的绝佳“肢体”。网上热传的“Playwright MCP”(Model Context Protocol)概念,其实就是把Playwright作为AI Agent执行Web操作的工具来用。所以,无论你是想提升测试效率,还是想开发一个能自动订票、自动处理工单的AI助手,Playwright都是你现在必须认真看待的工具。

2. 核心设计思路与优势解析

2.1 架构理念:为何“现代”是关键词

Playwright的“现代性”体现在它的架构设计上,这直接解决了传统工具的诸多痛点。它不像Selenium那样依赖一个独立的、需要额外维护的浏览器驱动(如ChromeDriver)。Playwright通过其自带的 playwright-core 库,直接与浏览器进行通信。当你执行 npx playwright install 时,它会把对应版本的浏览器二进制文件(Chromium, Firefox, WebKit)下载到本地缓存中。这意味着你的测试环境是 自包含的、版本锁定的 ,避免了“在我机器上能跑”的经典问题。

这种设计带来了几个立竿见影的好处:

  1. 启动速度快 :无需通过WebDriver协议层层转发,通信更直接。
  2. 功能更强大 :可以暴露更多底层浏览器能力,比如拦截修改网络请求、模拟地理位置、设备型号(这比单纯的User-Agent模拟更真实)、甚至生成PDF。这些在Selenium中实现起来要么很麻烦,要么根本不行。
  3. 自动等待机制 :这是Playwright最让人舒心的特性之一。它的大部分操作(如 click , fill , waitForSelector )都内置了智能等待。它会等待元素可操作(可见、启用、稳定)后才执行动作,极大减少了测试脚本中充斥的 Thread.sleep 或复杂等待条件。你写出来的代码干净、健壮。

2.2 与Selenium/Puppeteer的横向对比

很多人会问,有Selenium和Puppeteer了,为什么还要学Playwright?这张表能说清楚:

特性维度 Playwright Selenium Puppeteer
浏览器支持 Chromium, Firefox, WebKit(三位一体) 通过驱动支持所有主流浏览器 仅Chromium(Chrome)
架构 自带浏览器,直接通信 基于WebDriver标准,需独立驱动 基于DevTools协议,控制Chrome
自动等待 内置且强大 ,是核心特性 需要手动实现(WebDriverWait) 部分内置,但不如Playwright全面
网络拦截 原生支持 ,可轻松模拟API响应 可通过代理实现,较复杂 支持,但API相对底层
移动端模拟 通过设备描述符 原生模拟 ,非常逼真 可通过选项模拟,功能有限 支持,但同样不如Playwright丰富
录制功能 自带GUI录制工具 ,生成可靠代码 依赖IDE插件,代码质量参差不齐 无官方录制工具
多页面/上下文 优秀 ,隔离的BrowserContext概念清晰 支持,但管理稍显繁琐 支持
社区与生态 快速增长,微软背书,文档优秀 极其成熟,生态庞大但碎片化 成熟,主要围绕Chrome生态

实操心得 :如果你项目要求必须测IE(但愿没有),那Selenium是唯一选择。如果你只需要控制Chrome做爬虫或监控,Puppeteer很轻量。但如果你要 编写可靠、易维护的跨浏览器自动化脚本,或者为AI应用提供Web交互能力 ,Playwright的综合优势非常明显。它的API设计更人性化,错误信息也更友好,对新手和团队协作更友好。

2.3 为何成为AI应用开发的“标配”?

AI应用开发,特别是AI Agent,核心流程是“感知-思考-执行”。Playwright完美解决了“执行”环节中与Web GUI交互的难题。

  1. 可靠的执行器 :大模型可以生成操作步骤(“点击登录按钮”、“在搜索框输入XXX”),但需要一个能稳定执行这些步骤的工具。Playwright的高成功率和对复杂页面的处理能力,使得AI生成的指令能可靠落地。
  2. 丰富的上下文获取 :AI需要了解当前页面状态才能做出决策。Playwright可以轻松获取页面全文、截图、元素属性、网络请求响应,这些都能作为上下文喂给大模型。
  3. “录制-生成”加速开发 :你可以先用Playwright的录制功能,手动完成一遍业务流程,生成基础脚本。然后让AI(如GPT-4)去理解、重构、泛化这个脚本,甚至根据自然语言指令修改它。这大大降低了开发AI Agent的门槛。
  4. 与MCP等框架集成 :Model Context Protocol等框架正在将Playwright标准化为AI Agent的工具之一。这意味着未来你的AI Agent可以像调用函数一样,直接调用 playwright.click(selector) 这样的能力。

3. 从零开始:环境搭建与核心API精讲

3.1 一站式环境安装与配置

别被网上各种复杂的教程吓到,Playwright的安装可能是主流工具里最简单的。这里以Node.js环境为例(Python和.NET版本流程类似)。

第一步:项目初始化与安装

# 1. 新建你的项目目录
mkdir my-playwright-project && cd my-playwright-project

# 2. 初始化npm项目(如果还没有package.json)
npm init -y

# 3. 安装Playwright核心库
npm install playwright

重要提示 :这里安装的 playwright 包,已经包含了 playwright-core 安装浏览器所需的命令行工具 。这是最推荐的方式。

第二步:安装浏览器 安装完库后,你需要安装实际的浏览器二进制文件。

# 一次性安装所有支持的浏览器(Chromium, Firefox, WebKit)
npx playwright install

# 或者,如果你只需要其中一种,比如Chromium
npx playwright install chromium

# 对于国内网络环境,如果下载慢或失败,可以使用镜像
PLAYWRIGHT_DOWNLOAD_HOST=https://npmmirror.com/mirrors/playwright npx playwright install chromium

npx playwright install 这个命令会从官方仓库或你配置的镜像下载浏览器,并存放到 ~/.cache/ms-playwright 目录(Linux/Mac)或 %USERPROFILE%\AppData\Local\ms-playwright (Windows)。这个过程是自动的。

第三步:验证安装 创建一个简单的测试脚本 test.js

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: false }); // 有头模式启动,方便观察
  const page = await browser.newPage();
  await page.goto('https://example.com');
  console.log(await page.title());
  await page.screenshot({ path: 'example.png' });
  await browser.close();
})();

运行 node test.js 。如果能看到浏览器打开、访问example.com、控制台打印标题并截图保存,那么恭喜你,环境搞定!

避坑指南

  1. 权限问题 :在Linux/Mac上,如果遇到浏览器无法启动,可能是缓存目录权限问题。尝试 sudo chmod -R 755 ~/.cache/ms-playwright
  2. 依赖缺失 :Playwright的浏览器需要一些系统库(如libgtk)。官方安装脚本通常会尝试自动安装。如果启动失败,请参考Playwright官方文档的“系统要求”部分,手动安装缺失的库。例如在Ubuntu上: sudo apt-get install libwoff1 libopus0 libwebp6 libwebpdemux2 libenchant-2-2 libgudev-1.0-0 libsecret-1-0 libhyphen0 libgdk-pixbuf2.0-0 libegl1 libgles2 libevent-2.1-7
  3. “手动安装”的误解 :热搜里的 npx playwright install 手动安装 可能是指跳过自动下载,使用本地已存在的浏览器。这可以通过设置环境变量 PLAYWRIGHT_BROWSERS_PATH 指向你的浏览器目录来实现,但普通用户不建议,版本管理会很麻烦。

3.2 核心API与最佳实践

Playwright的API设计非常直观,围绕几个核心对象: Browser , BrowserContext , Page , Frame , Locator 。理解它们的关系至关重要。

1. Browser, Context 和 Page:清晰的隔离层级

const { chromium } = require('playwright');
(async () => {
  // 启动一个浏览器实例
  const browser = await chromium.launch({ headless: true });
  
  // 创建一个浏览器上下文 (Context)。Context是独立的会话环境,拥有独立的cookie、缓存、权限设置。
  // 这比直接创建Page更强大,常用于模拟多个用户或隔离测试。
  const context = await browser.newContext({
    viewport: { width: 1920, height: 1080 },
    userAgent: 'Mozilla/5.0 ...',
    // 可以在此处设置全局的权限,如地理位置
    permissions: ['geolocation'],
    // 可以拦截所有请求
    // extraHTTPHeaders: { 'Authorization': 'Bearer ...' }
  });
  
  // 在Context中创建一个页面 (Page)
  const page = await context.newPage();
  await page.goto('https://your-app.com');
  
  // 你可以创建多个Context和Page,它们彼此隔离
  const anotherContext = await browser.newContext();
  const anotherPage = await anotherContext.newPage();
  
  await browser.close();
})();

最佳实践 :为每个独立的测试用例或用户会话创建一个新的 BrowserContext ,而不是重复使用同一个Page。这样能保证测试的隔离性,避免状态污染。

2. Locator:定位元素的现代方式 Playwright极力推荐使用 Locator API,它代表一个随时可以查找的元素,并且内置了等待和重试机制。

// 传统方式(仍然可用,但不推荐作为首选)
await page.click('button#submit');

// 现代方式:使用Locator
const submitButton = page.locator('button#submit');
await submitButton.click(); // 点击前会自动等待元素可见、可点击

// Locator支持链式调用和复杂的筛选
await page.locator('table')
          .locator('tr', { hasText: 'John' })
          .locator('button.edit')
          .click();

// 最强大的:使用 getByRole, getByText, getByLabel 等语义化定位器
// 这是编写可访问且稳定测试的首选
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByText('Welcome back', { exact: true }).click();
await page.getByLabel('User Name').fill('testuser');

getByRole 等语义化定位器是Playwright的杀手锏之一。它们不依赖于易变的CSS选择器或XPath,而是基于ARIA角色和可访问性属性,这使得你的测试脚本在UI微调时也能保持稳定。

3. 自动等待与断言 无需再写 sleep 或复杂的 waitFor

// 导航并等待页面达到“网络空闲”状态
await page.goto('https://example.com', { waitUntil: 'networkidle' });

// 等待元素出现(最多等待30秒,默认)
await page.locator('.dynamic-content').waitFor({ state: 'visible' });

// 等待某个条件成立
await expect(page).toHaveTitle('Expected Title');
await expect(page.locator('.status')).toHaveText('Success');
// Playwright Test内置了丰富的断言,如上所示

4. 处理弹窗、下载、请求拦截

// 监听并处理弹窗(如window.open)
page.on('popup', async popup => {
  await popup.waitForLoadState();
  console.log(await popup.title());
});

// 监听下载
const [download] = await Promise.all([
  page.waitForEvent('download'), // 等待下载事件
  page.locator('a.download-link').click() // 触发下载
]);
const path = await download.path(); // 临时文件路径
await download.saveAs('/path/to/save.pdf'); // 保存文件

// 拦截和修改网络请求
await page.route('**/api/*', async route => {
  const response = await route.fetch();
  const json = await response.json();
  json.mocked = true; // 修改响应数据
  await route.fulfill({ response, json });
});

网络拦截功能在测试中模拟后端异常、加速测试(通过阻断不必要的资源加载)或为AI应用构造训练数据时极其有用。

4. 实战演练:构建一个完整的自动化测试流程

光说不练假把式。我们用一个接近真实的场景来串联所有知识点: 测试一个待办事项(Todo)应用的增删改查功能,并生成带视频的报告

4.1 项目结构与测试编写

我们使用Playwright Test作为测试运行器,它比直接用Playwright API写脚本更强大,支持并行、重试、报告生成等。

第一步:初始化Playwright Test项目 如果你之前只安装了 playwright ,现在需要安装测试运行器:

npm init playwright@latest

这个命令会交互式地帮你创建配置文件、测试目录和示例测试。我们假设项目结构如下:

my-todo-test/
├── package.json
├── playwright.config.js  # 配置文件
├── tests/
│   └── todo.spec.js     # 测试文件
└── tests-examples/       # 示例文件

第二步:编写测试用例 ( todo.spec.js )

const { test, expect } = require('@playwright/test');

// 在每个测试运行前,跳转到测试页面。这里我们用一个在线的TodoMVC示例。
test.beforeEach(async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc');
});

test('应该能添加一个新的待办事项', async ({ page }) => {
  // 使用语义化定位器找到输入框
  const newTodo = page.getByPlaceholder('What needs to be done?');
  
  // 输入内容并回车
  await newTodo.fill('Buy milk');
  await newTodo.press('Enter');
  
  // 断言:列表中应该出现这个事项,且复选框未勾选
  await expect(page.getByTestId('todo-title')).toHaveText('Buy milk');
  await expect(page.getByTestId('todo-item').first().locator('input[type="checkbox"]')).not.toBeChecked();
  
  // 顺便验证一下底部的计数
  await expect(page.getByTestId('todo-count')).toContainText('1 item left');
});

test('应该能标记一个事项为已完成', async ({ page }) => {
  // 先添加两个事项
  await page.getByPlaceholder('What needs to be done?').fill('Task 1');
  await page.getByPlaceholder('What needs to be done?').press('Enter');
  await page.getByPlaceholder('What needs to be done?').fill('Task 2');
  await page.getByPlaceholder('What needs to be done?').press('Enter');
  
  // 勾选第一个事项的复选框
  await page.getByTestId('todo-item').nth(0).getByRole('checkbox').check();
  
  // 断言:第一个事项应该有‘completed’类,计数变为1
  await expect(page.getByTestId('todo-item').nth(0)).toHaveClass(/completed/);
  await expect(page.getByTestId('todo-count')).toContainText('1 item left');
  
  // 切换到“Active”过滤器,应该只看到未完成的Task 2
  await page.getByRole('link', { name: 'Active' }).click();
  await expect(page.getByTestId('todo-item')).toHaveCount(1);
  await expect(page.getByTestId('todo-title')).toHaveText('Task 2');
});

test('应该能删除一个待办事项', async ({ page }) => {
  await page.getByPlaceholder('What needs to be done?').fill('Item to be deleted');
  await page.getByPlaceholder('What needs to be done?').press('Enter');
  
  // 鼠标悬停在事项上,使删除按钮出现
  const todoItem = page.getByTestId('todo-item');
  await todoItem.hover();
  
  // 点击删除按钮
  await todoItem.getByRole('button', { name: 'Delete' }).click();
  
  // 断言列表为空
  await expect(page.getByTestId('todo-list')).toBeEmpty();
});

4.2 运行测试与生成报告

运行测试:

# 以有头模式运行所有测试(方便调试)
npx playwright test --headed

# 以无头模式运行(CI环境常用)
npx playwright test

# 运行特定文件
npx playwright test tests/todo.spec.js

# 运行带有标签的测试
npx playwright test --grep "add"

# 在特定浏览器上运行(如 Firefox)
npx playwright test --project=firefox

生成并查看报告: Playwright Test默认会在运行后生成HTML报告。但更强大的是与Allure等报告框架集成。

# 1. 首先,运行测试并指定输出为Allure格式
npx playwright test --reporter=line,allure-playwright

# 2. 生成Allure报告
npx allure generate ./allure-results --clean

# 3. 打开报告
npx allure open ./allure-report

在Allure报告中,你可以看到清晰的测试套件、通过率、耗时,以及 每个失败测试的截图、追踪(Trace)和视频 。热搜中提到的“playwright allure报告 失败视频”就是指这个功能。当测试失败时,Playwright可以自动录制整个测试过程的视频和交互追踪(一个zip文件),这对于调试那些“时好时坏”的偶发性失败简直是神器。

配置追踪和视频: playwright.config.js 中启用:

const config = {
  use: {
    // ... 其他配置
    trace: 'on-first-retry', // 仅在第一次重试时记录追踪(节省资源)
    video: 'retain-on-failure', // 仅保留失败测试的视频
    // video: 'on'  // 录制所有测试的视频
  },
};

4.3 与CI/CD集成

将Playwright测试集成到GitHub Actions中非常简单。 创建一个 .github/workflows/playwright.yml 文件:

name: Playwright Tests
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: '18'
    - name: Install dependencies
      run: npm ci
    - name: Install Playwright Browsers
      run: npx playwright install --with-deps chromium # 只安装Chromium以加快CI速度
    - name: Run Playwright tests
      run: npx playwright test
    - uses: actions/upload-artifact@v4
      if: always() # 无论测试是否通过,都上传报告
      with:
        name: playwright-report
        path: playwright-report/
        retention-days: 30

这样,每次代码推送或PR都会自动运行测试,并将HTML报告上传为制品,供下载查看。

5. 进阶技巧与疑难问题排查

5.1 处理复杂场景:iframe、文件上传、身份验证

1. 与iframe内的元素交互 现代网页(如在线编辑器、支付页面)大量使用iframe。

// 方法1:通过frame对象
const frame = page.frame({ name: 'editor-frame' }); // 通过name
// 或 const frame = page.frame({ url: /.*payment.*/ }); // 通过URL
await frame.locator('button.submit').click();

// 方法2:使用FrameLocator (更推荐)
const editor = page.frameLocator('iframe[name="editor-frame"]');
await editor.locator('button.submit').click();
// FrameLocator也可以链式调用
await page.frameLocator('.outer-frame').frameLocator('.inner-frame').getByText('OK').click();

2. 文件上传 Playwright让文件上传变得异常简单,它模拟了操作系统级别的文件选择对话框。

// 最常见的场景:input[type="file"]
await page.locator('input[type="file"]').setInputFiles('/path/to/my/file.pdf');

// 上传多个文件
await page.locator('input[type="file"]').setInputFiles(['/path/to/file1.pdf', '/path/to/file2.jpg']);

// 动态生成文件(如测试用)
const buffer = Buffer.from('some text data', 'utf-8');
await page.locator('input[type="file"]').setInputFiles({
  name: 'test.txt',
  mimeType: 'text/plain',
  buffer: buffer
});

3. 处理身份验证(登录状态持久化) 很多测试需要登录状态。你可以登录一次,然后保存上下文状态,供后续测试复用。

const { chromium } = require('playwright');
(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();
  
  // 执行登录操作
  await page.goto('https://your-app.com/login');
  await page.fill('#username', 'testuser');
  await page.fill('#password', 'password');
  await page.click('button[type="submit"]');
  await page.waitForURL('**/dashboard'); // 等待登录成功跳转
  
  // 将登录后的状态保存到文件
  await context.storageState({ path: 'auth-state.json' });
  await browser.close();
})();

// 在另一个脚本或测试中,直接加载这个状态
const context2 = await browser.newContext({ storageState: 'auth-state.json' });
const page2 = await context2.newPage();
await page2.goto('https://your-app.com/dashboard'); // 此时已是登录状态

5.2 性能优化与稳定性提升

1. 选择性安装浏览器 在CI服务器或Docker镜像中,为了节省空间和时间,可以只安装需要的浏览器。

npx playwright install chromium
# 在 playwright.config.js 中,也只配置 Chromium 项目

2. 使用BrowserContext复用 创建BrowserContext比启动浏览器快得多。如果你的测试是顺序执行,可以考虑复用同一个Browser实例,但为每个测试创建新的Context。

test.describe('一组测试', () => {
  let browser;
  let context;
  
  test.beforeAll(async () => {
    browser = await chromium.launch();
  });
  
  test.beforeEach(async () => {
    context = await browser.newContext(); // 每个测试获得干净的上下文
    page = await context.newPage();
  });
  
  test.afterEach(async () => {
    await context.close();
  });
  
  test.afterAll(async () => {
    await browser.close();
  });
});

3. 合理配置超时与重试 playwright.config.js 中全局配置,或在测试中局部配置。

// playwright.config.js
export default {
  timeout: 30000, // 每个测试全局超时30秒
  expect: {
    timeout: 5000, // 每个expect断言超时5秒
  },
  // 失败重试,对于不稳定的测试有用,但要慎用,可能掩盖真正问题
  retries: process.env.CI ? 2 : 0, // CI环境下重试2次
};

// 在测试中局部配置
test('slow test', async ({ page }) => {
  test.slow(); // 标记为慢测试,超时时间会翻倍
  // 或者 test.setTimeout(60000);
});

5.3 常见问题排查实录

问题1:元素定位不到,报错 TimeoutError: page.locator(...).waitFor(...) 这是最常见的问题。

  • 可能原因1:元素在iframe或Shadow DOM里 。用 page.frameLocator() locator.shadowRoot()
  • 可能原因2:选择器不对或元素属性动态变化 。优先使用 getByRole , getByText , getByTestId 等语义化定位器。使用Playwright Inspector ( playwright codegen --debug ) 来录制并查看推荐的选择器。
  • 可能原因3:页面没有加载完或元素尚未出现 。确保在操作前使用了 page.waitForLoadState('networkidle') locator.waitFor()
  • 排查技巧 :在测试中加入 await page.pause(); ,运行测试时它会打开调试器,让你可以逐步执行、查看当前页面状态和尝试不同的选择器。

问题2:在CI(如GitHub Actions)上运行失败,本地却成功

  • 可能原因1:浏览器依赖缺失 。确保CI步骤中运行了 npx playwright install --with-deps --with-deps 会安装系统依赖)。
  • 可能原因2:资源加载超时或环境差异 。CI环境网络可能较慢,适当增加 navigationTimeout actionTimeout 。使用 page.goto(url, { waitUntil: 'domcontentloaded' }) 而不是默认的 'load' ,有时更快。
  • 可能原因3:内存不足 。无头模式默认会启动多个浏览器实例并行运行测试。如果CI机器内存小,可以在配置中限制并行数: workers: 1

问题3:如何处理需要“小额免密”支付之类的复杂交互? 热搜里提到了“用 playwright 自动提交 alipay 表单 + 小额免密”。这本质上是一个 自动化流程 状态处理 问题。

  1. 导航到支付页面 ,填写表单(使用 page.fill )。
  2. 处理可能的新窗口/iframe :支付宝支付通常会弹出一个新窗口或嵌入一个iframe。使用 page.waitForEvent('popup') page.frameLocator 来获取这个新上下文。
  3. 模拟用户选择“小额免密” :在新的上下文里,定位到“同意协议并支付”或类似的复选框和按钮,进行点击。这可能需要你仔细查看支付页面的HTML结构。
  4. 关键点 :这类操作涉及真实的金融流程, 仅用于测试你自己可控的沙箱环境 。绝对不要在生产或他人的真实支付环境进行自动化,这违反服务条款且存在法律和安全风险。对于测试,支付宝、微信支付等都提供了 沙箱环境 ,专门用于模拟支付流程。

问题4: playwright install 下载太慢或失败

  • 使用镜像 :如前所述,设置环境变量 PLAYWRIGHT_DOWNLOAD_HOST
  • 手动下载 (不推荐):从Playwright的GitHub Releases页面找到对应版本的浏览器包,手动解压到缓存目录。但版本管理会很头疼。
  • 检查网络 :确保能访问 https://playwright.azureedge.net

问题5:脚本在Windows/Linux/Mac上行为不一致

  • 路径分隔符 :文件路径使用 path.join() path.sep 来保证跨平台。
  • 换行符 :如果断言文本内容,注意不同系统的换行符可能是 \n \r\n 。使用正则表达式或 textContent 代替 innerText 进行模糊匹配。
  • 字体渲染 :截图对比测试可能因字体差异失败。考虑使用相同的测试字体,或对截图进行抗锯齿忽略处理。

Playwright的生态还在快速演进,围绕它的测试框架、报告工具、云服务(如Microsoft Playwright Testing)也在不断丰富。把它当成一个不仅用于测试,更能用于任何需要自动化浏览器场景的“瑞士军刀”,你会发现它的潜力远超预期。尤其是在AI应用开发浪潮下,一个能精准操控浏览器的工具,其价值会愈发凸显。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值