1. 项目概述为什么选择 Playwright 录制作为自动化测试的起点如果你是一名测试工程师或者是一名希望提升项目交付质量的全栈开发者那么“自动化测试”这个词对你来说一定不陌生。但一提到自动化测试很多人脑海中浮现的第一个画面可能就是面对着一行行复杂的代码需要理解各种定位器、等待机制和断言逻辑学习曲线陡峭维护成本高昂。这常常让初学者望而却步也让一些项目在初期难以快速落地自动化。今天我想分享一个能极大降低自动化测试入门门槛的实践使用 Playwright 的脚本录制功能从零开始构建你的第一个自动化测试脚本。Playwright 是微软开源的一个现代端到端测试框架它支持 Chromium、Firefox 和 WebKit 三大浏览器引擎这意味着你可以用一套脚本测试在不同浏览器上的表现。而它的脚本录制器Codegen功能堪称是“自动化测试的脚手架”。你不需要写一行代码只需要像真实用户一样操作浏览器它就能自动生成对应的测试脚本。这听起来是不是有点像“魔法”但它的价值远不止于生成代码。通过录制你可以快速理解 Playwright 的 API 设计、元素定位逻辑和操作流程为后续编写更复杂、更健壮的测试脚本打下坚实基础。无论是测试一个简单的登录流程还是一个包含多步骤的电商下单场景录制功能都能让你在几分钟内获得一个可运行的测试原型。2. 核心思路与工具选型为什么是 Playwright 而非 Selenium在开始动手之前我们有必要厘清一个核心问题市面上自动化测试框架那么多为什么偏偏选择 Playwright尤其是对比老牌的 SeleniumPlaywright 的优势在哪里这直接关系到我们后续脚本的稳定性、开发效率和维护成本。2.1 架构与性能的降维打击Selenium 通过 WebDriver 协议与浏览器通信这是一个标准但相对古老的协议。而 Playwright 则直接通过 DevTools Protocol 等更底层的渠道与浏览器对话。这种架构差异带来了几个关键优势执行速度更快Playwright 的 API 调用更直接避免了 WebDriver 协议的一些额外开销。自动等待机制这是 Playwright 最令人称道的特性之一。它的大部分操作如click,fill都内置了智能等待会等待元素可操作可见、可点击、可输入后才执行极大减少了测试脚本中因页面加载或元素状态不稳定而需要手动添加sleep或显式等待的情况。而 Selenium 需要开发者显式地处理各种等待条件对新手极不友好。强大的网络拦截与模拟Playwright 可以轻松地拦截和修改网络请求这对于测试需要 Mock 接口数据的场景比如你搜索热词中的“yapi mock 自动化测试”来说是杀手级功能。你可以直接让某个 API 返回预设的响应而无需修改后端代码或搭建复杂的 Mock 服务。2.2 脚本录制体验的差异虽然 Selenium IDE 也提供录制功能但其生成的脚本通常比较脆弱定位器策略单一过度依赖易变的 XPath 或 CSS 选择器且与现代前端框架如 React, Vue的动态 DOM 兼容性不佳。Playwright 的录制器则聪明得多生成多种定位器它会尝试为同一个元素生成多个定位器选项如getByRole,getByText,getByTestId并优先选择更稳定、语义化的方式。贴近真实编码习惯生成的代码结构清晰使用了 Page Object 模式的雏形通过page对象操作方便后续重构和封装。跨浏览器支持录制时即可选择在哪种浏览器内核下进行生成的脚本天然支持多浏览器运行。2.3 应对“UI大改”的韧性热词中提到了“即使ui大改脚本也能复现的方法”这恰恰是 Playwright 的强项。除了录制时生成多种定位器在后续维护中我们可以主动采用更稳健的定位策略使用语义化定位器优先使用getByRole(‘button’, { name: ‘提交’ })或getByText(‘登录’)而不是依赖于容易变化的 CSS 类名或 DOM 结构。利用测试专用属性与开发团队约定为关键交互元素添加># 1. 在你的项目目录初始化并安装 Playwright npm init -y npm install playwright/test # 2. 安装浏览器驱动。这是关键步骤如果直接 npx playwright install 失败可以使用镜像源 # 方法一使用系统环境变量推荐一劳永逸 # Windows (PowerShell): $env:PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright npx playwright install chromium firefox webkit # Linux/macOS: PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright npx playwright install chromium # 方法二使用 .npmrc 配置镜像针对 npm # 在项目根目录或用户目录创建 .npmrc 文件加入 playwright_download_hosthttps://npmmirror.com/mirrors/playwright # 然后再执行安装命令注意playwright/test包包含了运行测试所需的库和命令行工具。安装浏览器驱动是独立的步骤因为驱动文件体积较大。务必确保网络通畅或正确配置镜像否则会卡在下载阶段。对于 Python 项目pip install playwright # 安装驱动 playwright install chromium # 如果安装慢同样可以尝试设置环境变量原理相同安装成功后你可以通过npx playwright --version来验证。3.2 认识脚本录制器Playwright Codegen录制功能通过playwright codegen命令启动。它不仅仅是一个“录屏工具”更是一个交互式的学习与开发环境。实时生成代码你在浏览器里的每一次点击、输入、跳转都会实时转换成代码显示在侧边栏或独立窗口中。支持多种语言你可以选择生成 Python、Java、C# 或 JavaScript/TypeScript 的代码满足不同技术栈的需求。元素选择器探查你可以点击录制器界面上的“选择元素”按钮然后去页面上点击任意元素它会显示 Playwright 推荐的所有可能定位器并高亮当前使用的那个。这是学习如何编写稳健定位器的绝佳方式。启动录制器的基本命令是npx playwright codegen [website-url]例如npx playwright codegen https://demo.playwright.dev/todomvc会打开一个浏览器和一个代码生成窗口开始录制在 TodoMVC 应用上的操作。4. 实战录制第一个自动化测试脚本理论说得再多不如亲手操作一遍。让我们以一个经典的场景——在某个演示网站进行用户登录和简单操作——来完整走一遍录制流程。4.1 录制目标与场景设计假设我们要测试一个简单的任务管理应用。核心流程如下访问应用首页。点击“登录”按钮。在登录表单中输入用户名和密码。点击“提交”登录。登录成功后在任务输入框中添加一个新任务“学习 Playwright 录制”。验证任务是否成功添加到列表。这个流程涵盖了打开页面、点击、输入文本、断言等基本操作是一个理想的入门案例。4.2 分步录制与代码生成启动录制器打开终端执行npx playwright codegen https://your-demo-app.com。将地址替换成任何你有权限测试的登录页面例如 GitHub 登录页但请注意不要泄露真实凭证建议使用专门测试环境。执行操作浏览器窗口打开后你会看到旁边有一个“Playwright Inspector”窗口显示着生成的代码初始是空的。在浏览器中点击“登录”按钮。观察 Inspector 窗口你会立刻看到生成了类似page.getByRole(‘button’, { name: ‘登录’ }).click();的代码。在出现的表单中点击用户名输入框然后输入test_user。你会看到生成了page.getByLabel(‘用户名’).fill(‘test_user’);的代码。Playwright 智能地使用了getByLabel因为它关联了label标签。同理填写密码字段。点击提交按钮。登录后找到任务输入框输入“学习 Playwright 录制”并按回车或点击添加按钮。停止与保存操作完成后不要关闭浏览器。直接在 Playwright Inspector 窗口中点击顶部的“复制”按钮或者点击“保存”按钮将生成的代码保存为一个.spec.js或.py文件。4.3 生成的代码深度解析让我们看看录制生成的 JavaScript 代码可能是什么样子并逐行分析const { test, expect } require(‘playwright/test’); // 引入测试框架 test(‘添加任务流程’, async ({ page }) { // 定义一个测试用例 await page.goto(‘https://your-demo-app.com’); // 导航到页面 // 点击登录按钮 await page.getByRole(‘button’, { name: ‘登录’ }).click(); // 填写登录表单 await page.getByLabel(‘用户名或邮箱’).fill(‘test_user’); await page.getByLabel(‘密码’).fill(‘your_password’); await page.getByRole(‘button’, { name: ‘提交’ }).click(); // 等待导航完成通常登录后会跳转 await page.waitForURL(‘**/dashboard’); // 这是一个很好的实践确保页面已跳转 // 添加新任务 await page.getByPlaceholder(‘添加新任务…’).fill(‘学习 Playwright 录制’); await page.getByRole(‘button’, { name: ‘添加’, exact: true }).click(); // 断言验证新任务出现在列表中 await expect(page.getByText(‘学习 Playwright 录制’)).toBeVisible(); });代码亮点分析自动等待所有的click(),fill()操作前面都有await并且 Playwright 内部已经处理了等待元素可用的逻辑。稳健的定位器代码使用了getByRole,getByLabel,getByPlaceholder,getByText等语义化定位器。这些定位器比基于class或复杂XPath的定位器更不容易受 UI 样式变更的影响。清晰的流程代码顺序完全反映了用户操作流程可读性极高。加入了断言录制器在最后自动添加了一个断言这是构成一个完整测试的关键。实操心得录制时操作速度可以稍微慢一点、确定一点。有时快速连续的操作可能导致录制器漏掉某些步骤。如果发现生成的代码缺失了某个操作你可以手动在 Inspector 里暂停然后重新执行那个操作。5. 从录制脚本到可维护的测试用例录制得到的脚本是一个完美的起点但直接将其作为最终的自动化测试用例可能还略显粗糙。我们需要对其进行“精加工”使其更健壮、更易维护。5.1 优化定位器策略录制器生成的定位器有时可能不是最优的。你需要审查并优化它们优先顺序getByTestIdgetByRole/getByLabelgetByTextgetByPlaceholdercss/xpath。避免绝对文本getByText(‘提交’)可能不如getByRole(‘button’, { name: ‘提交’ })稳定因为按钮的文本可能被国际化或微调。如果必须用文本可以考虑使用正则表达式进行部分匹配如getByText(/submit/i)。使用exact选项当页面有多个相似文本时使用{ exact: true }来精确匹配避免误定位。5.2 重构与引入 Page Object 模式当测试用例越来越多时将页面元素定位和操作封装成 Page Object 是行业最佳实践。这能极大提升代码复用性和可维护性。重构示例创建登录页面对象(login-page.js)class LoginPage { constructor(page) { this.page page; this.usernameInput page.getByLabel(‘用户名或邮箱’); this.passwordInput page.getByLabel(‘密码’); this.submitButton page.getByRole(‘button’, { name: ‘提交’ }); } async navigate() { await this.page.goto(‘https://your-demo-app.com/login’); } async login(username, password) { await this.usernameInput.fill(username); await this.passwordInput.fill(password); await this.submitButton.click(); // 可以在这里添加等待登录成功的逻辑 await this.page.waitForURL(‘**/dashboard’); } } module.exports { LoginPage };修改测试脚本const { test, expect } require(‘playwright/test’); const { LoginPage } require(‘./pages/login-page’); const { DashboardPage } require(‘./pages/dashboard-page’); // 假设也有Dashboard页 test(‘使用 Page Object 登录并添加任务’, async ({ page }) { const loginPage new LoginPage(page); const dashboardPage new DashboardPage(page); await loginPage.navigate(); await loginPage.login(‘test_user’, ‘your_password’); await dashboardPage.addTask(‘学习 Playwright 录制’); await expect(dashboardPage.getTask(‘学习 Playwright 录制’)).toBeVisible(); });这样一来如果登录页面的输入框label变了你只需要在一个地方LoginPage类修改定位器所有用到这个登录操作的测试用例都无需改动。5.3 添加配置与数据驱动环境配置将测试环境的 URL、登录凭证等敏感信息从代码中剥离放入配置文件如playwright.config.js中的use.baseURL或环境变量中。数据驱动使用test.describe和参数化测试来用多组数据运行同一流程。Playwright Test 支持使用test.extend配合forEach或外部数据文件如 JSON, CSV来实现。6. 高级技巧与疑难问题排查即使有了录制和基础封装在实际项目中还是会遇到各种问题。下面分享一些高级技巧和常见问题的排查思路。6.1 处理动态元素与复杂等待问题页面元素是动态加载的如 AJAX 列表录制时生成了getByText(…)但运行时元素还没出现导致测试失败。解决使用locator与 Web-First AssertionsPlaywright 的断言如expect(locator).toBeVisible()是自动重试的。确保你对动态元素的断言使用的是expect。// 正确断言会自动等待直到元素可见超时前 await expect(page.getByText(‘动态加载的内容’)).toBeVisible(); // 避免直接操作如果元素未加载会立即失败 // await page.getByText(‘动态加载的内容’).click();自定义等待对于非可见性条件可以使用page.waitForSelector(但更推荐使用locator.waitFor) 或page.waitForFunction。// 等待列表项数量大于0 await page.locator(‘.todo-list li’).first().waitFor({ state: ‘attached’ }); // 或者等待某个特定状态 await page.waitForFunction(() document.querySelector(‘.status’).textContent ‘完成’);6.2 应对 iframe、新窗口和弹窗问题操作流程中涉及 iframe 内的元素或浏览器弹窗。解决iframe需要先获取frame对象然后在它上面进行定位。const frame page.frame({ name: ‘editor-frame’ }); // 通过 name 或 url 定位 await frame.locator(‘button’).click(); // 录制器在录制 iframe 内操作时通常能自动生成正确的 frame 定位代码。新窗口/标签页使用page.context()来监听新页面。const [newPage] await Promise.all([ page.context().waitForEvent(‘page’), // 监听新页面事件 page.locator(‘a[target“_blank”]’).click() // 触发打开新页面的操作 ]); await newPage.waitForLoadState(); // 后续操作 newPage弹窗 (dialog)使用page.on(‘dialog’)事件监听器来处理。page.on(‘dialog’, async dialog { console.log(弹窗信息: ${dialog.message()}); await dialog.accept(); // 点击“确定” // 或 await dialog.dismiss(); // 点击“取消” });6.3 调试与问题排查实录当测试失败时不要慌张。系统性地排查查看错误信息与截图Playwright Test 默认会在失败时截屏和保存追踪。在playwright.config.js中确保以下配置已开启use: { trace: ‘on-first-retry’, // 或 ‘retain-on-failure’ 以保留追踪文件 screenshot: ‘only-on-failure’, },运行测试时使用--headed模式在 UI 下运行可以直观看到哪一步失败了。使用 Playwright Inspector 手动调试除了录制Inspector 也是一个强大的调试工具。用PWDEBUG1环境变量运行测试它会以调试模式启动允许你一步步执行查看每个步骤的定位器、快照和网络情况。# Linux/macOS PWDEBUG1 npm test # Windows (PowerShell) $env:PWDEBUG1; npm test检查定位器在浏览器开发者工具中使用 Playwright 提供的Playwright Selector功能需要安装浏览器扩展来验证你的定位器是否唯一、准确地找到了目标元素。分析网络与时间如果失败与数据加载有关检查测试的等待逻辑是否足够。考虑在关键操作后增加page.waitForLoadState(‘networkidle’)或等待特定请求完成。6.4 集成与持续运行一个独立的脚本价值有限集成到 CI/CD 流水线中才能发挥自动化测试的最大价值。使用 Playwright Test Runner我们一直用的playwright/test就是一个完整的测试运行器。你可以用它来组织测试套件、并行执行、生成报告。生成报告在playwright.config.js中配置reporter可以生成 HTML、JSON、JUnit 等格式的报告方便集成到 Jenkins、GitLab CI 等平台。npx playwright test --reporterhtml # 运行后会生成一个漂亮的 HTML 报告展示了测试通过率、耗时、失败截图和追踪。在 CI 中运行在 GitHub Actions、GitLab CI 等环境中需要安装依赖、浏览器驱动然后以无头模式运行测试。官方提供了详细的 CI 配置示例。从点击录制按钮到生成第一行代码再到构建起一个健壮、可维护、可集成的自动化测试套件Playwright 的脚本录制功能扮演了至关重要的“领航员”角色。它降低了入门门槛让你能快速看到自动化测试的成效建立信心。更重要的是通过分析和优化录制生成的代码你能深入理解 Playwright 的设计哲学和最佳实践。记住录制是开始不是结束。结合 Page Object 模式、稳健的定位器策略、合理的等待机制和持续的集成你才能打造出真正经得起项目迭代考验的自动化测试体系。下次当你面对一个全新的 Web 应用时不妨先打开playwright codegen让它带你走完第一遍流程你会发现自动化测试的起点远比想象中更近。