Playwright入门指南:从零开始掌握跨浏览器自动化测试
1. 初识Playwright:现代Web测试的瑞士军刀
第一次听说Playwright时,我正在为一个电商项目焦头烂额地调试Selenium脚本。那会儿最让我头疼的就是不同浏览器间的兼容性问题,直到同事推荐了这个微软开源的测试工具。Playwright给我的第一印象就像是个"全能选手"——它不仅能同时支持Chromium、Firefox和WebKit三大浏览器引擎,还能用我熟悉的Python语言编写脚本。
这个工具最吸引我的地方在于它的"真实感"。比如在测试一个下拉菜单时,传统的工具可能需要手动添加等待时间,而Playwright会自动等待元素真正可交互时才执行操作。有次我测试一个懒加载的图片墙,脚本竟然自动等待所有图片加载完成才进行截图,这让我省去了大量调试时间。
实际项目中,我常用它来做这些事情:
- 检查页面在不同浏览器下的渲染一致性
- 自动化填写表单并验证提交结果
- 捕获页面加载过程中的性能指标
- 对单页应用(SPA)进行深度交互测试
2. 环境搭建:十分钟快速上手
记得第一次安装Playwright时,我特意记了时——从零开始到成功运行第一个测试只用了7分半钟。下面分享我最常用的Python环境配置方法,连终端命令都给你准备好了:
# 创建虚拟环境(可选但推荐)
python -m venv playwright-env
source playwright-env/bin/activate # Linux/Mac
# playwright-env\Scripts\activate # Windows
# 安装Playwright包
pip install playwright
# 安装浏览器二进制文件
playwright install
这里有个小技巧:如果你在国内,可能会遇到下载慢的问题。可以尝试设置环境变量来加速下载:
# 设置Playwright下载镜像源
set PLAYWRIGHT_DOWNLOAD_HOST=https://npmmirror.com/mirrors/playwright
playwright install
安装完成后,我习惯用这个"健康检查"脚本来验证环境:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://example.com")
print(f"页面标题:{page.title()}")
browser.close()
如果看到输出"页面标题:Example Domain",恭喜你,环境配置成功了!我第一次运行成功时,还特意截图发了朋友圈纪念。
3. 第一个测试脚本:从登录测试开始
让我们从一个真实的电商网站登录测试开始。我选择这个场景是因为它涵盖了:
- 页面导航
- 元素定位
- 表单填写
- 点击操作
- 结果验证
import re
from playwright.sync_api import expect
def test_login(page):
# 访问登录页面
page.goto("https://demo.opencart.com/admin")
# 断言页面标题
expect(page).to_have_title(re.compile("Administration"))
# 填写登录表单
page.get_by_label("Username").fill("demo")
page.get_by_label("Password").fill("demo")
# 点击登录按钮
page.get_by_role("button", name="Login").click()
# 验证登录后跳转
expect(page.get_by_role("heading", name="Dashboard")).to_be_visible()
这个脚本里我特别喜欢Playwright的智能等待机制。有次我在一个慢速网络环境下测试,发现它自动等待了足足15秒直到登录按钮变为可点击状态,而传统工具这时早就超时报错了。
元素定位方面,我推荐优先使用这些方法:
get_by_role()- 通过ARIA角色定位get_by_label()- 关联label文本get_by_placeholder()- 通过占位文本get_by_text()- 通过可见文本
尽量避免使用xpath,就像上个月我维护的一个项目,前端改了DOM结构导致大量xpath定位失效,而使用语义化定位的脚本全都安然无恙。
4. 进阶技巧:处理常见疑难杂症
在实际项目中,我遇到过不少"坑",这里分享三个最有用的解决方案:
场景一:处理动态加载元素 上周测试一个使用无限滚动的页面时,我这样等待特定商品出现:
# 传统方式(不推荐)
page.wait_for_timeout(5000) # 固定等待5秒
# Playwright推荐方式
product = page.get_by_text("限量版球鞋")
product.wait_for(state="visible") # 最多等待30秒
场景二:文件上传测试 测试文件上传功能时,我发现Playwright的处理特别优雅:
# 单文件上传
page.get_by_label("上传头像").set_input_files("avatar.jpg")
# 多文件上传
page.get_by_label("上传作品集").set_input_files([
"work1.jpg",
"work2.pdf"
])
场景三:跨iframe操作 昨天刚解决的一个支付iframe问题:
# 定位到支付iframe
frame = page.frame_locator("iframe[name='payment']")
# 在iframe内操作
frame.get_by_placeholder("卡号").fill("4111111111111111")
frame.get_by_text("确认支付").click()
还有个特别实用的功能是网络请求拦截,我在测试错误处理时经常用:
# 模拟API返回500错误
page.route("**/api/checkout", lambda route: route.abort())
5. 跨浏览器测试实战
Playwright最强大的功能之一就是真正的跨浏览器测试。这是我上个月做兼容性测试的配置:
import pytest
from playwright.sync_api import Page
@pytest.mark.parametrize("browser_type", ["chromium", "firefox", "webkit"])
def test_search(browser_type, request):
playwright = request.getfixturevalue("playwright")
browser = getattr(playwright, browser_type).launch()
page = browser.new_page()
page.goto("https://example.com/search")
page.get_by_placeholder("搜索").fill("Playwright")
page.get_by_role("button", name="搜索").click()
expect(page.locator("#results")).to_contain_text("Playwright")
browser.close()
测试中发现一个有趣的差异:WebKit对CSS动画的处理与其他浏览器不同,导致我们的下拉菜单在Safari中显示异常。多亏了这个测试,我们提前发现了问题。
移动端测试也很简单:
iphone = playwright.devices["iPhone 13"]
browser = playwright.chromium.launch()
context = browser.new_context(**iphone)
page = context.new_page()
6. 调试与问题排查
调试是自动化测试中最耗时的环节,Playwright提供了几个神器:
1. Playwright Inspector
在终端运行测试时加上--debug参数:
pytest --debug
会启动一个GUI调试器,可以:
- 单步执行
- 查看实时DOM
- 修改定位器
- 查看执行日志
2. 追踪记录 在配置中添加:
context.tracing.start(screenshots=True, snapshots=True)
# 测试结束后
context.tracing.stop(path="trace.zip")
然后用playwright show-trace trace.zip查看完整的测试回放。
3. 视频录制 这是我上周排查一个偶发bug时的配置:
context = browser.new_context(record_video_dir="videos/")
# 测试结束后
page.close()
context.close()
7. 持续集成实践
在GitHub Actions中我是这样配置的:
name: Playwright Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- run: pip install playwright pytest-playwright
- run: playwright install
- run: pytest tests/ --browser=all
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
有个小技巧:在CI中我通常会启用headless模式并设置超时更长:
browser = playwright.chromium.launch(
headless=True,
timeout=60000 # 60秒超时
)
8. 最佳实践与性能优化
经过十几个项目的实践,我总结了这些经验:
目录结构建议
tests/
├── fixtures/
├── page_objects/ # 页面对象模型
├── test_cases/
├── utils/ # 工具函数
└── conftest.py # pytest配置
页面对象模式示例
class LoginPage:
def __init__(self, page):
self.page = page
self.username = page.get_by_label("Username")
self.password = page.get_by_label("Password")
self.submit = page.get_by_role("button", name="Login")
def navigate(self):
self.page.goto("https://example.com/login")
def login(self, user, pwd):
self.username.fill(user)
self.password.fill(pwd)
self.submit.click()
性能优化技巧
- 复用浏览器上下文:每个测试类只创建一次
- 并行执行:
pytest -n auto - 禁用不必要的资源加载:
context.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
断言策略
# 不推荐
assert "成功" in page.text_content("#message")
# 推荐
expect(page.locator("#message")).to_contain_text("成功")
expect(page).to_have_url(re.compile(r"/dashboard"))
最近一个项目中,通过这些优化将测试套件执行时间从23分钟降到了4分钟,团队的小伙伴们都惊呆了。
更多推荐


所有评论(0)