Playwright脚本录制:从零到一构建Web自动化测试

📅 发布时间:2026/7/18 3:03:55
Playwright脚本录制:从零到一构建Web自动化测试 1. 项目概述为什么我们需要录制脚本做Web自动化测试的朋友估计都经历过一个阶段手动写代码。从定位元素开始一行行敲driver.find_element_by_xpath再到模拟点击、输入、断言。这个过程不仅枯燥而且对新手来说定位元素就是个老大难问题一个复杂的下拉框或者动态加载的列表可能就得折腾半天。更别提那些需要处理iframe、新窗口或者复杂验证码的场景了。所以当听到“录制脚本”这四个字时很多人的眼睛会放光。这听起来太美好了我像正常用户一样操作一遍浏览器工具在旁边默默看着然后自动生成一套可以重复执行的代码。这不就是“所见即所得”的自动化吗Playwright作为近几年在自动化测试领域声名鹊起的后起之秀它的脚本录制功能官方称之为Playwright Inspector或Codegen正是为了解决这个痛点而生。它不是一个独立的“录制器”软件而是深度集成在Playwright工具链中的一个核心能力旨在让测试脚本的创建变得像使用浏览器开发者工具一样直观。简单来说这个项目的核心价值在于降低自动化测试的入门门槛和初期构建成本。无论你是测试工程师、开发人员还是想自动化一些网页操作的产品经理都可以通过录制快速得到一个可运行的基础脚本框架然后再基于此进行精细化修改和增强。这比从零开始写要高效得多也准确得多毕竟机器“看”到的操作和你实际执行的操作是完全一致的。2. Playwright录制功能深度解析2.1 Playwright Inspector不只是录制器很多人把Playwright的录制功能简单理解为一个“录屏转代码”的工具这其实低估了它。Playwright Inspector是一个交互式的调试和代码生成环境。当你以特定模式启动浏览器时它会打开两个窗口一个是你要操作的浏览器页面另一个是Inspector界面。Inspector的核心功能有三块录制Record这是大家最熟悉的功能。你在浏览器里的每一次点击、输入、滚动都会被实时转换成对应语言的代码如Python, JavaScript, Java, .NET显示在Inspector的代码面板中。定位Pick Locator这是比录制更基础、也更强大的功能。你可以点击Inspector上的“选择元素”按钮然后在浏览器页面上点击任意元素Inspector会立刻在代码面板中生成定位该元素的最佳选择器通常是get_by_role,get_by_text,get_by_test_id这类Playwright推荐的、稳定性更高的定位器而不是直接给你一个又长又脆弱的XPath。调试与回放Debug Replay生成代码后你可以在Inspector里直接点击“运行”来执行这段脚本观察回放效果。更重要的是你可以一步步执行步进查看每一步执行后的页面状态、网络请求和Console日志这对于调试脚本为什么失败至关重要。这种设计理念意味着Playwright希望你将录制作为脚本创作的起点而非终点。录制得到的是一个可靠的、基于上下文的最佳实践代码草稿然后你可以利用Inspector的交互能力去打磨它。2.2 录制背后的原理它到底“录”了什么理解原理能帮你更好地使用和调试。当你启动录制模式时Playwright做了以下几件事启动一个被“监听”的浏览器上下文这不是一个普通的浏览器实例。Playwright会通过CDPChrome DevTools Protocol或其他浏览器私有协议与浏览器建立深度连接。这个连接通道允许Playwright捕获所有来自用户和浏览器本身的事件。事件监听与转换Playwright监听的是底层DOM事件和浏览器API调用而不是屏幕像素变化。当你点击一个按钮它捕获到的是在某个特定元素上触发的click事件当你输入文本它捕获的是对输入框元素的input或fill事件。然后Playwright的智能引擎会根据捕获到的事件类型、目标元素的信息标签、属性、文本、可访问性角色等结合其内置的“定位器引擎”计算出最稳定、最简洁的代码来复现这个操作。代码生成计算出的操作和定位器会被转换成你指定的编程语言的Playwright API调用。这里有个关键点Playwright倾向于生成使用其Locator API的代码比如page.get_by_role(“button”, name“Submit”).click()而不是page.click(“#submit-btn”)。因为Locator API基于语义化角色和文本通常比基于CSS或XPath的定位器更能抵抗前端微小的样式或结构变化。所以它“录”的是一系列精确的、可编程的浏览器交互指令而不是图像或坐标。这保证了生成代码的准确性和可维护性。3. 从零开始录制你的第一个自动化脚本理论说得再多不如动手操作一遍。这里我以Python环境为例带你走通全流程。假设我们要录制一个在百度首页搜索“Playwright”的简单脚本。3.1 环境准备与安装首先确保你的机器上已经安装了Python建议3.8。然后通过pip安装Playwright。# 安装playwright库 pip install playwright # 安装Playwright所需的浏览器驱动Chromium, Firefox, WebKit playwright install注意playwright install这一步非常重要且必须。它会下载三大浏览器Chromium、Firefox、WebKit的可执行文件到本地缓存。这些不是完整的浏览器而是Playwright优化过的专用版本保证了自动化环境的一致性。如果跳过这一步后续运行会报错。安装完成后你可以通过命令行快速验证录制功能playwright codegen执行这个命令它会自动打开Chromium浏览器和Inspector界面。但今天我们不用这种方式因为我们要创建的是一个可保存、可复用的项目文件。3.2 使用官方模板快速启动录制更工程化的做法是先创建一个Python脚本文件比如record_demo.py然后在其中以编程方式启动录制。但Playwright提供了一个更简单的方式使用--target参数指定生成代码的语言和框架。不过对于初学者我推荐以下“手把手”方式理解每一步在做什么创建脚本文件新建一个名为test_record.py的文件。编写启动代码在文件中输入以下内容。这段代码的作用是同步启动一个浏览器打开新页面并开启录制模式将生成的代码输出到标准输出终端或指定文件。from playwright.sync_api import Playwright, sync_playwright def run(playwright: Playwright): # 启动一个Chromium浏览器实例headlessFalse表示显示图形界面 browser playwright.chromium.launch(headlessFalse) # 创建一个新的浏览器上下文类似于一个独立的隐身会话 context browser.new_context() # 在新上下文中打开一个空白页 page context.new_page() # 关键步骤启动录制并将生成的代码指向我们的Python文件 # 实际上更常见的做法是直接使用playwright codegen命令。 # 但为了理解原理我们可以用page.pause()方法它也会调出Inspector并进入录制模式。 print(“打开浏览器后请操作页面。操作完成后在Inspector中点击‘Resume’即可生成代码。”) page.pause() # 这行代码会暂停脚本执行打开Inspector # 后续的关闭操作会在你结束录制后执行 context.close() browser.close() with sync_playwright() as playwright: run(playwright)运行并录制在终端执行python test_record.py。首先会弹出一个Chromium浏览器窗口。紧接着会弹出Playwright Inspector窗口。此时脚本执行在page.pause()处暂停。你在浏览器窗口中的所有操作都会被录制。在浏览器地址栏输入https://www.baidu.com回车。在搜索框输入“Playwright”。点击“百度一下”按钮。生成与保存代码操作完成后不要关闭浏览器。切换到Playwright Inspector窗口你可以看到它已经实时生成了对应的Python代码。点击Inspector上的“Copy”按钮复制所有生成的代码。然后点击“Resume”按钮或按F8让之前暂停的脚本继续执行它会关闭浏览器。整合代码用你复制的代码替换掉test_record.py中page.pause()及其之后的所有内容。一个完整的、可独立运行的脚本就诞生了。它看起来会类似这样from playwright.sync_api import Playwright, sync_playwright def run(playwright: Playwright): browser playwright.chromium.launch(headlessFalse) context browser.new_context() page context.new_page() # 以下是录制生成的代码 page.goto(“https://www.baidu.com/“) page.get_by_role(“textbox”, name“百度一下”).click() page.get_by_role(“textbox”, name“百度一下”).fill(“playwright”) page.get_by_role(“button”, name“百度一下”).click() # 录制结束 # 为了看清结果我们等待一会儿 page.wait_for_timeout(3000) context.close() browser.close() with sync_playwright() as playwright: run(playwright)3.3 录制实战技巧与避坑指南第一次录制通常不会一帆风顺这里分享几个我踩过坑才总结出的技巧技巧一慢工出细活操作要“优雅”录制时你的操作速度不要太快。特别是页面加载比较慢的时候如果你在一个元素还没完全出现时就点击Playwright可能会生成一个page.wait_for_timeout(5000)这样的固定等待这不是最佳实践。理想的做法是稍微等一下页面稳定再进行下一个操作。更好的方式是事后将固定等待改为基于条件的等待比如page.wait_for_selector(“text搜索结果”)。技巧二理解生成的定位器仔细观察生成的代码page.get_by_role(“textbox”, name“百度一下”)。这里用了get_by_role这是Playwright推荐的定位方式。role是ARIA角色name是 accessible name。这种定位方式不依赖于具体的ID或CSS类名只要这个输入框的语义角色和可访问名称不变即使前端样式大改你的脚本也能正常运行。如果Inspector生成了很长的XPath你可以手动点击Inspector上的“Pick Locator”工具让它重新推荐一个更好的定位器。技巧三处理弹窗和新窗口如果你录制的操作会触发弹窗alert, confirm, prompt或在新标签页打开链接Playwright也能处理。对于弹窗它会生成page.on(“dialog”, …)事件监听代码。对于新窗口你需要通过监听context.on(“page”, …)事件来获取新页面的引用然后在新页面对象上操作。录制时按正常流程操作即可Playwright会记录下这些上下文切换。常见坑点元素定位失败回放脚本时最常见的错误。原因可能是1) 页面还没加载完2) 元素在iframe里3) 元素是动态生成的。解决方案在操作前增加等待page.wait_for_selector定位iframepage.frame_locator(“iframe”).locator(“button”)或使用更稳定的定位策略如get_by_test_id需要开发配合添加>import pytest from playwright.sync_api import Page, expect pytest.fixture(scope“function”) def page(browser): # browser是另一个fixture用于管理浏览器实例 context browser.new_context() page context.new_page() yield page context.close() def test_baidu_search(page: Page): page.goto(“https://www.baidu.com”) search_box page.get_by_role(“textbox”, name“百度一下”) search_box.click() search_box.fill(“playwright”) page.get_by_role(“button”, name“百度一下”).click() # 使用Playwright的断言 expect(page).to_have_title(regex“.*playwright.*”)使用Pytest后你可以获得用例管理、夹具依赖、并行执行、报告生成等强大功能。使用Page Object Model (POM) 设计模式这是UI自动化测试的黄金法则。将页面元素定位和操作封装成类。# pages/search_page.py class SearchPage: def __init__(self, page: Page): self.page page self.search_box page.get_by_role(“textbox”, name“百度一下”) self.search_button page.get_by_role(“button”, name“百度一下”) def navigate(self): self.page.goto(“https://www.baidu.com”) def search_for(self, keyword: str): self.search_box.click() self.search_box.fill(keyword) self.search_button.click() # test case def test_search_with_pom(page: Page): search_page SearchPage(page) search_page.navigate() search_page.search_for(“playwright”) expect(page).to_have_title(regex“.*playwright.*”)POM的最大好处是将元素定位与测试逻辑分离。当前端页面修改时你只需要更新对应的Page类中的定位器所有测试用例无需改动。4.2 增加健壮性等待与断言录制生成的代码往往缺少必要的等待和断言。用智能等待替代固定等待永远避免使用page.wait_for_timeout(5000)除非是调试。使用Playwright提供的自动等待和显式等待。自动等待Playwright的绝大多数操作如click,fill本身就有自动等待机制它会等待元素可操作可见、稳定、未被遮挡。所以通常你不需要额外等待。显式等待用于等待特定条件成立。这是最推荐的方式。# 等待元素出现 page.wait_for_selector(“text搜索完成”) # 等待导航完成 page.wait_for_url(“**/search**”) # 使用expect进行等待式断言推荐 expect(page.locator(“.search-result”)).to_have_count(10)添加丰富的断言断言是测试的灵魂。Playwright通过expect模块提供了丰富的匹配器。expect(page).to_have_title(“Playwright - 百度搜索”) expect(page.locator(“.result”)).to_have_count(10) expect(page.get_by_text(“操作成功”)).to_be_visible() expect(page).to_have_screenshot(“search_result.png”) # 视觉对比4.3 处理复杂场景文件上传录制时点击文件上传按钮选择文件Playwright会生成page.set_input_files(“input[type‘file’]”, “path/to/file”)代码。这是最可靠的方式。下拉选择对于select元素录制会生成page.select_option(“select#country”, “china”)。对于自定义的下拉组件可能需要先点击触发下拉再点击选项。鼠标悬停与键盘操作录制鼠标悬停Hover和组合键操作如CtrlC是支持的。Playwright会生成page.hover(“menuitem”)和page.keyboard.press(“ControlC”)这样的代码。5. 进阶将录制集成到CI/CD与大型项目单个脚本的录制和优化只是开始。真正的价值在于将其融入团队的开发流程。5.1 与Playwright Test Runner深度集成Playwright提供了自己的测试运行器playwright/testfor JS/TSpytest-playwrightfor Python。它比裸的Pytest集成度更高提供了内置的夹具、并行测试、视频录制、追踪查看器Trace Viewer等强大功能。使用Playwright Test Runner你的配置文件如playwright.config.py可以定义各种浏览器、设备模拟、全局超时、截图和视频配置。录制生成的用例可以很容易地迁移到这个框架下享受其所有生态福利。5.2 在CI/CD中运行在GitHub Actions, GitLab CI, Jenkins等环境中运行Playwright脚本是标准操作。核心步骤包括依赖安装安装Python、Node.js如果需要、Playwright库。浏览器安装运行playwright install --with-depsCI环境通常需要安装系统依赖。执行测试运行pytest或playwright test命令。上传产物将测试报告HTML报告、截图、追踪文件.zip作为产物保存便于失败时排查。一个简单的GitHub Actions配置示例name: Playwright Tests on: [push] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - uses: actions/setup-pythonv4 with: python-version: ‘3.10’ - name: Install dependencies run: | pip install -r requirements.txt playwright install --with-deps chromium - name: Run tests run: pytest --browserchromium --headed - uses: actions/upload-artifactv3 if: always() with: name: playwright-report path: playwright-report/ retention-days: 305.3 大型项目管理录制作为脚手架在大型项目中录制功能的最佳定位是快速创建测试用例的脚手架。具体工作流可以是产品经理或测试人员录制一个核心业务流程生成基础脚本。自动化开发工程师接收脚本进行POM重构、添加健壮的等待和断言、参数化测试数据。将优化后的用例纳入测试套件配置到CI/CD流水线中。当页面发生重大变更时可以再次使用录制功能快速更新对应Page Object中的定位器和操作流而不是手动重写。6. 常见问题排查与性能优化即使脚本写好了运行中也会遇到各种问题。这里记录一些典型问题的排查思路。6.1 问题排查清单问题现象可能原因排查步骤与解决方案元素定位不到 (Locator not found)1. 页面未加载完成。2. 元素在iframe/Shadow DOM内。3. 定位器本身不稳定如依赖动态ID。4. 页面有多个匹配项。1. 在操作前添加page.wait_for_load_state(‘networkidle’)或等待特定元素出现。2. 使用page.frame_locator()定位iframe或page.locator(‘…’).shadow_root处理Shadow DOM。3. 使用Inspector的“Pick Locator”重新选择优先使用get_by_role,get_by_text。4. 使用first,nth,filter等方法精确定位。操作超时 (Timeout)1. 网络慢或接口响应慢。2. 元素一直达不到可操作状态如一直被遮挡。3. 等待条件设置不合理。1. 适当增加全局或局部超时时间timeout参数。2. 检查是否有弹窗、遮罩层遮挡了目标元素。3. 检查等待条件是否永远无法满足改用其他条件。脚本在本地通过CI上失败1. CI环境缺少依赖或浏览器。2. CI环境资源CPU/内存不足。3. 网络环境或测试数据不同。4. 无头模式下的细微差异。1. 确保CI步骤中正确安装了浏览器playwright install --with-deps。2. 尝试在CI上使用--headed模式运行一次看是否有界面错误。3. 使用Playwright的追踪功能Tracing这是大杀器。在配置中启用trace: ‘on-first-retry’失败时会上传trace.zip文件用Playwright Trace Viewer打开可以逐帧查看所有操作、网络请求、Console日志像看录像一样定位问题。回放速度与操作不一致1. 录制时操作有思考时间回放是连续执行。2. 缺少必要的等待导致操作在元素出现前就触发。1. 这是正常现象自动化就是为了快。如果业务逻辑依赖时间间隔可适当添加page.wait_for_timeout()但需谨慎。2. 确保关键步骤后有正确的等待条件。6.2 性能与稳定性优化复用浏览器上下文创建和启动浏览器的开销很大。在测试套件级别通过fixture复用同一个浏览器实例和上下文可以极大提升执行速度。并行执行Playwright Test Runner和Pytest都支持并行运行测试。合理规划测试用例避免状态污染利用多核CPU大幅缩短整体测试时间。选择性启用/禁用功能视频录制、追踪文件生成会消耗大量磁盘I/O和CPU。在CI环境中可以配置为仅在测试失败时生成追踪文件trace: ‘on-first-retry’和截图screenshot: ‘only-on-failure’。使用稳定的定位器这是维护成本的决定性因素。从一开始就坚持使用>