Playwright 高级用法全解析:从自动化到测试工程化的进阶指南
当你用Playwright完成基础UI自动化(如元素定位、点击输入)后,是否会遇到“复杂场景难实现、用例维护成本高、故障排查效率低”等问题?其实Playwright的强大之处不仅在于“开箱即用”,更在于其提供的**高级特性**——从网络拦截、自定义驱动到并行执行与报告集成,这些功能能帮你构建“稳定、高效、可扩展”的测试体系。本文从实战角度出发,详解6个Playwright高级用法,附完整代码示例,带你从“会用”升级到“精通”。
一、高级用法1:网络拦截与Mock(解决“依赖外部接口”痛点)
在UI自动化中,测试结果常依赖外部接口(如支付接口、第三方登录接口),若接口不稳定或返回随机数据,会导致用例“偶发失败”。Playwright的**网络拦截功能**可直接拦截请求、修改响应,甚至Mock接口返回,彻底摆脱对外部依赖的依赖。
核心能力
拦截指定URL/域名的请求;
修改请求参数(如Header、Body);
Mock响应数据(自定义返回结果,无需调用真实接口);
阻断不必要的请求(如广告、统计接口,加速用例执行)。
实战场景与代码示例
场景1:Mock登录接口,跳过真实登录流程
假设登录接口/api/login
需要正确的账号密码才能返回成功,用Mock可直接返回“登录成功”,跳过输入账号密码的步骤,大幅提升用例执行速度。
from playwright.sync_api import sync_playwrightdef test_mock_login():with sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page()# 1. 拦截登录接口,Mock成功响应def handle_login_request(route, request):# 自定义Mock响应:登录成功,返回Tokenmock_response = {"code": 200,"message": "登录成功","data": {"token": "mock_token_123", "username": "test_user"}}# 发送Mock响应(状态码200,JSON格式)route.fulfill(status=200,content_type="application/json",body=json.dumps(mock_response))# 拦截所有匹配 "/api/login" 的POST请求page.route("**/api/login", handle_login_request)# 2. 访问登录页,触发登录请求(无需输入真实账号密码)page.goto("https://example.com/login")# 点击登录按钮(此时触发的请求会被Mock)page.get_by_test_id("login-btn").click()# 3. 断言登录成功(跳转到首页,显示用户名)page.wait_for_url("https://example.com/home")assert page.get_by_test_id("username").text_content() == "test_user"browser.close()
场景2:拦截图片/广告请求,加速页面加载
页面中的图片、广告、统计接口会占用加载时间,拦截这些请求可让用例执行速度提升30%以上。
def test_block_unnecessary_requests():with sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page()# 拦截并阻断指定类型的请求def block_request(route, request):# 阻断图片(png/jpg)、广告(ad)、统计(analytics)请求if any(keyword in request.url for keyword in [".png", ".jpg", ".jpeg", "ad.", "analytics."]):route.abort() # 阻断请求else:route.continue_() # 允许其他请求继续# 拦截所有请求page.route("**/*", block_request)# 访问页面,加载速度会显著提升page.goto("https://example.com")print("页面加载完成,耗时:", page.evaluate("performance.timing.loadEventEnd - performance.timing.navigationStart"), "ms")browser.close()
二、高级用法2:自定义浏览器配置(适配复杂环境)
基础用法中,我们通常用默认浏览器配置(如默认分辨率、无插件),但实际测试场景中可能需要:
模拟不同分辨率(如手机、平板);
加载扩展插件(如AdBlock、Vue DevTools);
保留登录状态(避免每次用例重新登录);
配置代理(测试海外环境或抓包分析)。
Playwright支持通过browser.new_context()
自定义上述所有配置,满足复杂环境需求。
实战代码示例
示例1:模拟手机分辨率与UA
def test_mobile_simulation():with sync_playwright() as p:# 1. 自定义手机配置(分辨率375x812,UA为iPhone 13)mobile_context = browser.new_context(viewport={"width": 375, "height": 812}, # 手机分辨率user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1", # 手机UAis_mobile=True, # 标记为移动设备(会模拟触摸事件)has_touch=True # 支持触摸操作)page = mobile_context.new_page()# 2. 访问移动端页面,验证适配效果page.goto("https://example.com/mobile")# 断言移动端导航栏显示(而非PC端)assert page.get_by_test_id("mobile-nav").is_visible()mobile_context.close()browser.close()
示例2:保留登录状态(复用浏览器上下文)
每次用例重新登录会浪费大量时间,通过persistent_context
可保留Cookie和本地存储,实现“一次登录,多次复用”。
def test_reuse_login_state():with sync_playwright() as p:# 1. 创建持久化上下文(数据存储在指定目录)persistent_context = p.chromium.launch_persistent_context(user_data_dir="./chrome_data", # 数据存储目录(Cookie、LocalStorage)headless=False)page = persistent_context.new_page()# 2. 首次执行时登录,后续执行会自动保留登录状态if not page.url.startswith("https://example.com/home"):page.goto("https://example.com/login")# 输入账号密码登录(仅首次执行)page.get_by_test_id("username-input").fill("test_user")page.get_by_test_id("password-input").fill("test_pass")page.get_by_test_id("login-btn").click()page.wait_for_url("https://example.com/home")# 3. 直接操作已登录的页面page.get_by_test_id("my-order").click()assert page.url.startswith("https://example.com/order")persistent_context.close()
三、高级用法3:Playwright + Pytest 工程化(提升用例维护性)
当用例数量超过10条时,单纯的脚本文件会变得难以维护。结合Pytest框架,可实现**用例分层、参数化、前置后置、并行执行**等工程化能力,让测试体系更规范。
核心工程化特性
Fixture前置后置:复用登录、浏览器初始化等重复步骤;
参数化测试:用一组数据执行同一个用例(如多账号登录测试);
用例分组与标记:按模块(如登录、下单)或优先级(P0、P1)执行用例;
并行执行:多进程运行用例,缩短全量执行时间。
实战工程化配置
1. 全局Fixture配置(conftest.py)
# conftest.py(Pytest全局配置文件)
import pytest
from playwright.sync_api import Playwright, Browser, Page, BrowserContext
import json# 1. 读取配置文件(不同环境的URL、账号)
def load_config():with open("config.json", "r", encoding="utf-8") as f:return json.load(f)config = load_config()# 2. 浏览器Fixture(会话级别,所有用例复用一个浏览器)
@pytest.fixture(scope="session")
def browser(playwright: Playwright):browser = playwright.chromium.launch(headless=config["headless"], # 配置文件控制是否无头运行args=["--start-maximized"] # 浏览器最大化)yield browserbrowser.close()# 3. 上下文Fixture(用例级别,每个用例一个上下文,避免状态污染)
@pytest.fixture(scope="function")
def context(browser: Browser):context = browser.new_context(viewport={"width": 1920, "height": 1080}, # 桌面分辨率accept_downloads=True # 允许下载)# 全局添加请求拦截(阻断广告)context.route("**/*ad*", lambda route, request: route.abort())yield contextcontext.close()# 4. 页面Fixture(用例级别,自动登录)
@pytest.fixture(scope="function")
def page(context: BrowserContext):page = context.new_page()# 前置步骤:登录page.goto(config["base_url"] + "/login")page.get_by_test_id("username-input").fill(config["username"])page.get_by_test_id("password-input").fill(config["password"])page.get_by_test_id("login-btn").click()page.wait_for_url(config["base_url"] + "/home")yield page# 后置步骤:截图(用例失败时)if pytest.fail.occurred:page.screenshot(path=f"reports/screenshots/{pytest.current_test.name}.png", full_page=True)
2. 参数化用例示例
# test_login.py
import pytest
from playwright.sync_api import Page# 用例参数化:多组账号密码测试
@pytest.mark.parametrize("username, password, expect_success", [("valid_user", "valid_pass", True), # 有效账号("valid_user", "wrong_pass", False), # 密码错误("", "valid_pass", False), # 空账号
])
def test_login_parametrize(page: Page, username: str, password: str, expect_success: bool):# 重新访问登录页(清除之前的登录状态)page.goto("https://example.com/login")# 输入账号密码page.get_by_test_id("username-input").fill(username)page.get_by_test_id("password-input").fill(password)page.get_by_test_id("login-btn").click()# 断言结果if expect_success:page.wait_for_url("https://example.com/home")assert page.get_by_test_id("username").is_visible()else:assert page.get_by_test_id("login-error").is_visible()
3. 并行执行用例
安装pytest-xdist
后,通过-n
参数指定并行进程数,大幅缩短执行时间:
# 安装依赖
pip install pytest-xdist# 4进程并行执行所有用例
pytest test/ -n 4 --html=reports/test_report.html
四、高级用法4:元素交互高级技巧(解决“难定位、难操作”场景)
基础交互(如click()
、fill()
)能应对80%的场景,但遇到以下复杂元素时会失效:
动态生成的元素(如分页加载的列表);
隐藏元素(如hover后显示的菜单);
拖拽元素(如拖拽排序、拖拽上传);
键盘快捷键(如Ctrl+C、Enter)。
Playwright提供了针对性的高级交互API,轻松解决这些问题。
实战代码示例
1. 拖拽元素(Drag-and-Drop)
def test_drag_and_drop(page: Page):page.goto("https://example.com/drag-sort")# 定位拖拽源(要移动的元素)和目标位置drag_source = page.get_by_test_id("item-1")drag_target = page.get_by_test_id("item-3")# 执行拖拽操作(从源元素拖拽到目标元素)drag_source.drag_to(drag_target)# 断言排序结果(元素1应在元素3之后)items = page.locator(".sort-item").all_text_contents()assert items.index("Item 1") > items.index("Item 3")
2. Hover显示隐藏元素
def test_hover_element(page: Page):page.goto("https://example.com/menu")# 1. Hover到父菜单(显示子菜单)parent_menu = page.get_by_test_id("parent-menu")parent_menu.hover()# 2. 等待子菜单可见,点击子菜单选项child_menu = page.get_by_test_id("child-menu-item")child_menu.wait_for(state="visible")child_menu.click()# 断言跳转结果assert page.url == "https://example.com/child-page"
3. 键盘快捷键操作
def test_keyboard_shortcuts(page: Page):page.goto("https://example.com/editor")# 1. 在编辑器中输入文本editor = page.get_by_test_id("text-editor")editor.fill("Hello Playwright")# 2. 执行Ctrl+A(全选)→ Ctrl+C(复制)→ Ctrl+V(粘贴)page.keyboard.press("Control+A") # 全选page.keyboard.press("Control+C") # 复制page.keyboard.press("Control+V") # 粘贴# 断言结果(粘贴后文本应为"Hello PlaywrightHello Playwright")assert editor.text_content() == "Hello PlaywrightHello Playwright"
五、高级用法5:测试报告与故障排查(提升问题定位效率)
用例失败后,仅靠“元素未找到”的日志无法快速定位问题。Playwright结合Allure报告,可实现:
失败用例自动截图、录屏;
展示用例执行步骤、耗时、环境信息;
支持用例趋势分析、缺陷追踪。
实战配置步骤
1. 安装依赖
pip install allure-pytest playwright-plugin
2. 配置Allure报告(conftest.py补充)
# conftest.py中添加Allure相关Fixture
import allure
from playwright.sync_api import Page# 用例开始前添加环境信息到报告
@pytest.fixture(scope="session", autouse=True)
def add_environment_info():with allure.step("环境信息"):allure.attach("Chrome 124", name="浏览器版本")allure.attach("https://test.example.com", name="测试环境URL")allure.attach("Python 3.10", name="Python版本")# 用例失败时添加截图和录屏到报告
@pytest.fixture(scope="function", autouse=True)
def attach_screenshot_video(page: Page, request):yield# 检查用例是否失败if request.node.rep_call.failed:# 添加截图screenshot = page.screenshot(full_page=True)allure.attach(screenshot, name="失败截图", attachment_type=allure.attachment_type.PNG)# 添加录屏(需提前配置录屏)if page.video:video_path = page.video.path()allure.attach.file(video_path,name="用例录屏",attachment_type=allure.attachment_type.WEBM)
3. 生成并查看报告
# 1. 执行用例,生成Allure报告数据
pytest test/ -n 4 --alluredir=allure-results# 2. 生成HTML报告
allure generate allure-results -o allure-report --clean# 3. 打开报告(自动启动浏览器)
allure open allure-report
报告效果
报告中会包含:
用例通过率、执行时间统计;
每个用例的步骤详情(如“访问登录页”“输入账号”);
失败用例的截图、录屏(点击即可查看);
环境信息、浏览器版本等关键数据。
六、高级用法6:Playwright 与 CI/CD 集成(实现自动化闭环)
将Playwright用例集成到CI/CD流程(如Jenkins、GitHub Actions),可实现“代码提交后自动执行测试,失败及时通知”,形成测试自动化闭环。
GitHub Actions 集成示例(.github/workflows/playwright-test.yml)
name: Playwright UI Test# 触发条件:main分支代码提交或PR
on:push:branches: [ main ]pull_request:branches: [ main ]jobs:test:# 运行环境:Ubuntu最新版runs-on: ubuntu-lateststeps:# 1. 拉取代码- uses: actions/checkout@v4# 2. 安装Python- name: Set up Pythonuses: actions/setup-python@v5with:python-version: '3.10'# 3. 安装依赖- name: Install dependenciesrun: |python -m pip install --upgrade pippip install -r requirements.txt# 安装Playwright浏览器python -m playwright install chromium# 4. 执行测试(无头模式,生成Allure报告)- name: Run Playwright testsrun: |pytest test/ -n 4 --headless --alluredir=allure-results# 5. 上传报告到GitHub Artifacts(便于下载查看)- name: Upload Allure reportuses: actions/upload-artifact@v4with:name: allure-reportpath: allure-results# 6. 测试失败时发送邮件通知(可选)- name: Send failure notificationif: failure()uses: dawidd6/action-send-mail@v3with:server_address: smtp.office365.comserver_port: 587username: ${{ secrets.EMAIL_USERNAME }}password: ${{ secrets.EMAIL_PASSWORD }}subject: Playwright UI Test Failedbody: "UI测试失败,请查看GitHub Actions报告:${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"to: test-team@example.comfrom: Playwright CI
总结:Playwright 高级用法的核心价值
Playwright的高级用法并非“炫技”,而是为了解决实际测试场景中的痛点:
网络拦截:摆脱外部接口依赖,让用例更稳定;
自定义配置:适配不同环境(手机、代理、插件),提升测试覆盖率;
工程化集成:用Pytest+Allure让用例易维护、故障易排查;
CI/CD闭环:实现“代码提交→自动测试→结果通知”,提前发现问题。
掌握这些高级用法后,你不仅能应对复杂的UI自动化场景,更能构建一套“可扩展、可维护、高效率”的测试体系,让Playwright真正成为测试效率的“加速器”。