从Selenium到Playwright:快速入门指南
这些年,见证过太多测试工具的兴起与迭代。从早期的QTP到Selenium的黄金时代,再到如今各种现代化测试框架的百花齐放。今天想跟大家聊聊Playwright——这个让我在最近几个大型项目中,真正感受到“测试也可以很优雅”的工具。
认识Playwright:新一代的自动化测试框架
Playwright是什么?
简单来说,Playwright是由微软团队于2020年推出的一个开源自动化测试框架。它的定位非常明确:解决现代Web应用(特别是单页应用和渐进式Web应用)自动化测试中的痛点。
与很多测试框架不同,Playwright在设计之初就考虑到了现代Web开发的实际情况。它原生支持Chromium、Firefox和WebKit三大浏览器引擎,这意味着你可以用同一套脚本测试Chrome、Firefox和Safari的行为。更重要的是,它对这些浏览器的支持是通过直接通信协议实现的,而不是像传统工具那样依赖中间层。
为什么选择Playwright?与Selenium的深度对比
作为在测试行业摸爬滚打了18年的老手,我用过几乎所有主流的自动化测试工具。当团队第一次考虑从Selenium转向Playwright时,我们做了详细的评估。
架构设计:根本性的差异
这可能是两者最大的不同。Selenium基于WebDriver协议,通过HTTP与浏览器驱动通信;而Playwright则使用WebSocket建立双向通信通道。
这个差异在实际项目中意味着什么?
稳定性:Playwright的通信方式更稳定,不容易出现连接超时或中断
速度:WebSocket的实时双向通信比HTTP的请求-响应模式快得多
功能丰富性:Playwright可以直接监听浏览器事件,而不是被动轮询
开箱即用的体验
我还记得早期配置Selenium环境时,要下载对应版本的浏览器驱动,还要确保驱动和浏览器版本匹配。Playwright彻底解决了这个问题:
一行命令搞定所有环境
playwright install
它会自动下载匹配的浏览器二进制文件,版本完全对应,永远不用担心兼容性问题。对于需要频繁部署CI/CD的团队来说,这省去了大量的维护成本。
等待策略:智能与手动的区别
在Selenium中,我们常常需要写这样的代码:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "dynamic-element"))
)
而在Playwright中,自动等待是默认行为:
Playwright会智能等待元素可操作
page.locator("#dynamic-element").click()
这种设计理念的差异非常关键。Playwright的定位器(Locator)API在执行操作前会自动等待元素达到可用状态(可见、可点击、非禁用等),这大大减少了显式等待的代码量。
现代Web应用支持
对于使用React、Vue、Angular等框架构建的现代Web应用,Playwright有更好的支持:
Shadow DOM支持:原生支持,无需特殊处理
网络拦截:可以在测试中模拟各种网络条件,轻松测试加载状态和错误处理
移动端模拟:完整的设备模拟,包括视口、触摸事件、地理位置等
调试能力:差距明显
这是Playwright真正让我惊艳的地方。当测试失败时,Selenium通常只能提供一个截图和有限的日志。而Playwright提供了完整的执行追踪:
启用完整追踪
context.tracing.start(
screenshots=True,
snapshots=True, # 包含完整的DOM状态
sources=True # 包含测试源代码
)
生成的追踪文件可以通过可视化工具查看,你能看到:
每个操作步骤的屏幕截图
当时的完整DOM状态(可以交互!)
网络请求时间线
JavaScript控制台输出
这对于调试那些"在我机器上是好的"的偶发问题,价值无法估量。
多语言支持
两者都支持多种编程语言,但Playwright的API在不同语言间保持了高度一致性。这意味着:
团队中不同语言背景的成员可以快速协作
跨语言的知识迁移成本很低
官方文档的例子可以轻松转换成你使用的语言版本
环境搭建:五分钟快速上手
很多人觉得搭建环境麻烦,其实Playwright在这方面做得相当友好。
Python环境为例:
1. 安装Playwright库(国内镜像加速)
pip install playwright -i https://pypi.tuna.tsinghua.edu.cn/simple/
2. 安装浏览器驱动(建议全部安装,便于多浏览器测试)
playwright install
如果想按需安装,比如只需要Chrome
playwright install chromium
这里有个小建议:即使你目前只测Chrome,也最好把Firefox和WebKit一起装上。因为未来某天,产品经理可能会突然说“咱们需要验证下Safari上的兼容性”。Playwright的WebKit引擎能很好地模拟Safari行为,未雨绸缪总没错。
从“Hello World”到真实用例
官方文档的第一个例子通常是这样的:
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://www.baidu.com")
print(page.title())
browser.close()
但真实项目中,我们很少这样写。我建议从第一个脚本开始就养成良好的工程习惯:
conftest.py - 基础配置
import pytest
from playwright.sync_api import Page
@pytest.fixture(scope="session")
def browser_context_args(browser_context_args):
return {
**browser_context_args,
"viewport": {"width": 1920, "height": 1080},
"ignore_https_errors": True,
}
test_login.py - 真实测试用例
def test_user_login_success(page: Page):
"""测试用户正常登录流程"""
page.goto("https://your-app.com/login")
# Playwright的定位器(locator)API非常强大
page.locator("#username").fill("test_user")
page.locator("#password").fill("secure_password")
# 自动等待按钮可点击再操作
page.locator("button:has-text('登录')").click()
# 断言会自动等待条件成立
expect(page.locator(".user-avatar")).to_be_visible()
注意这里我用的是pytest-playwright插件,它提供了很多开箱即用的fixture。对于测试工程师来说,我强烈建议直接基于pytest来组织你的Playwright测试,而不是裸写脚本。这会让你后续的测试管理、报告生成、并行执行省心很多。
几个让效率翻倍的内置工具
- 录制生成代码(Codegen)新手最爱,老手偶尔也用:
playwright codegen https://your-app.com
这个不是让你完全依赖它生成代码,而是快速学习定位器写法。当你面对一个复杂页面不知道如何定位时,打开录制器操作一下,看看它生成的代码,比自己查文档快得多。
- 调试利器:Playwright Inspector
设置环境变量后运行测试
PWDEBUG=1 pytest test_demo.py
测试会在执行时暂停,并打开一个调试界面。你可以:
查看当前页面的DOM结构
实时生成元素选择器
单步执行测试代码
查看网络请求和console日志
3. 故障排查:Trace Viewer在测试失败时,光看日志和截图往往不够。Playwright的Trace功能能记录测试执行的完整上下文:
在测试中启用trace记录
context.tracing.start(screenshots=True, snapshots=True, sources=True)
... 执行测试操作
context.tracing.stop(path="trace.zip")
生成的trace.zip用playwright show-trace trace.zip命令打开,你会看到一个完整的测试回放,包括每个操作时的DOM快照、网络请求、甚至鼠标移动轨迹。对于排查那些“在我机器上好好的”的偶发问题,这个工具简直就是救命稻草。
给测试工程师的实践建议
- 定位器策略:优先考虑可测试性跟开发同学沟通,给关键元素加上data-testid属性:
在你的测试中:
page.locator("[data-testid=submit-button]").click()
这比用CSS选择器button.btn.primary:nth-child(2)稳定得多,也更容易理解。
- 页面对象模型(POM)的现代化演进传统的POM模式在Playwright中可以有更优雅的实现:
class LoginPage:
def init(self, page: Page):
self.page = page
self.username = page.locator("#username")
self.password = page.locator("#password")
self.submit = page.locator("button[type='submit']")
def login(self, username, password):
self.username.fill(username)
self.password.fill(password)
self.submit.click()
return HomePage(self.page) # 返回下一个页面对象
使用起来非常直观
def test_login():
login_page = LoginPage(page)
home_page = login_page.login("user", "pass")
assert home_page.is_loaded()
3. 并行执行配置在pytest.ini中加入:
ini
[pytest]
根据CPU核心数自动设置并行进程
addopts = -n auto
Playwright默认每个进程独立浏览器实例
这能让你的测试套件执行时间从几小时缩短到几十分钟。
什么时候选择Playwright?什么时候坚持Selenium?
经过多个项目的实践,我的建议是:
选择Playwright,如果:
你的应用是现代化的单页应用(SPA)
测试稳定性是你最关心的问题
你需要测试多浏览器行为(特别是移动端浏览器)
你的团队愿意接受相对较新的技术
你需要强大的调试和追踪能力
考虑坚持Selenium,如果:
你维护的是大量遗留的Selenium测试代码
你需要支持某些Playwright不支持的浏览器(如旧版IE)
你的团队对Selenium有深厚的知识积累
你需要使用Selenium Grid进行大规模分布式测试(不过Playwright也有自己的Grid方案了)
迁移策略:从Selenium到Playwright
如果你决定尝试Playwright,我建议采用渐进式迁移:
并行运行:在CI/CD中同时运行Selenium和Playwright测试,对比结果
新用例用Playwright:所有新功能测试直接用Playwright实现
逐步重写:当修改旧测试时,顺便将其重写为Playwright版本
完全切换:当大部分测试都迁移完成后,移除Selenium依赖
工具在变,但测试的本质不变
Playwright确实是一款让我眼前一亮的测试框架。但它也只是一个工具,真正的核心还是测试设计思想和对业务的理解。
如果你是从Selenium转过来的,可能需要一点时间适应它的异步思维。但一旦掌握,你会发现很多以前需要“硬编码”等待的地方,现在可以写得更加简洁可靠。
对于测试团队来说,引入Playwright不仅仅是换一个工具,更是一次提升测试工程化水平的机会。它的可调试性、可追踪性、多浏览器支持,都让测试活动变得更加“专业”。
工具在变,但测试的本质不变——用尽可能高效的方式,保障产品质量。Playwright是这个目标下的一个优秀选择。
纸上得来终觉浅,绝知此事要躬行。建议从一个小模块开始尝试,先写几个简单的用例感受一下。遇到问题多查官方文档(写得相当不错),或者去GitHub issues看看有没有类似讨论。测试工程师的成长,就是在解决一个个具体问题中积累起来的。

欢迎大家入群交流,领取免费学习资料

浙公网安备 33010602011771号