绝大多数 Selenium 和 Playwright 的性能对比,都是在理想环境下跑的合成测试:在专门做的演示应用里测按钮点击、表单填写、页面跳转,全是干净的 HTML,没有任何服务端渲染的意外状况。
这种结果只能体现理想条件下的框架开销,说明不了真实应用里的实际表现。
Sanzu Oracle APEX 电商门户 —— 就是我之前写 Playwright PCOM 和 AI 智能体文章时用的被测应用 —— 环境可以说一点都不理想。
APEX 运行时会生成动态 ID,几乎每次交互都会触发 AJAX 区域刷新,用会话式鉴权,重复登录会被限流,还有些 UI 元素完全靠 CSS 伪元素渲染,DOM 里根本不存在。
用它做测试,才是真刀真枪地检验两个框架在真实场景下,处理现代服务端驱动 Web 应用的能力。
我用 Selenium WebDriver(Ruby/RSpec)和 Playwright(TypeScript)各跑了一遍完全相同的 7 个测试,其中 Playwright 分别开了 1、2、3、4 个 worker。
这篇文章会讲清楚我测了什么、每个测试实际覆盖什么场景、两套框架的配置细节,以及数据反映的结论 —— 包括那些不符合常规认知的反常结果。
选哪些测试做性能对比,本身就是个设计决策。全选快的测试,测的其实是测试启动开销;全选慢的测试,测的就是应用本身,不是框架。我的目标是覆盖 APEX 电商应用里,有代表性的各类性能场景。
Sanzu 首页会加载 11 个商品卡片,每个都包含名称、原价 / 促销价、星级评分、折扣商品倒计时、“加入购物车” 按钮。HP-01 验证这 11 个卡片全部存在、结构正确。
这个测试的核心差异,在于两个框架在整页加载后,定位和校验大量元素的效率。
Selenium 每次元素查询都要走一次 HTTP 往返,规模上来之后开销会持续叠加;Playwright 用持久 WebSocket 连接加 CDP 集成,处理批量元素的效率要高得多。本来预期这是差距最大的测试项之一。
跳转登录页,填写账号密码,提交,断言浏览器最终落在/home路径。APEX 在服务端处理登录,返回重定向,URL 里嵌入新的会话 ID—— 所以测试要等 POST 请求和后续的 GET 跳转都完成。
这个测试代表所有鉴权类流程:表单交互加导航等待。APEX 的限流机制是个很真实的约束:如果账号错误,下一次登录会被冷却拦截,这也是种子用例里用Promise.race()同时匹配成功、限流、账号错误三种 URL 模式的原因。
同样的表单,故意输错密码。测试断言页面出现错误信息,且不发生页面跳转。APEX 是内联渲染错误 —— 不跳转、不刷新,靠局部页面更新实现。
有意思的地方在于“提交”到“断言”之间,两个框架的处理逻辑差异。
Selenium 通常要显式等待错误元素出现,Playwright 自带自动等待机制,断言本身就带重试逻辑,会一直重试直到条件满足或者超时。本来预期这个架构差异会带来非常明显的速度提升。
这个测试需要登录态。点击第一个商品的 “加入购物车”,等待购物车侧边栏组件更新总价。
购物车更新是典型的 APEX AJAX 区域刷新:点击按钮触发apex.server.process(),向服务端发请求,局部重渲染购物车组件,不整页刷新。
这个测试测的,是 APEX 交互模式里最容易让自动化出问题的场景:操作触发了可见变化,但没有导航事件。
依赖 URL 变化或页面加载判断 “有事情发生” 的框架,在这里会很吃力。Playwright 的waitForResponse或者元素状态等待,能很顺畅地处理这类场景。
从首页开始,保持登录态且购物车已有商品,测试先跳购物车页,再点击 “去结算”,断言结算页加载完成。整个流程串联两次 APEX 页面导航,都要求有效会话。
这个测试的 DOM 交互不多,主要是导航和重定向处理。预期两个框架速度差不多,因为元素交互极少,应用响应时间占主导,框架开销的影响很小。
跳转商品详情页,验证商品名称、描述、价格、加入购物车按钮都存在且可见。这是整套测试里最轻的一项 —— 一次简单导航,加上在单功能 APEX 页面上的几个元素断言。
加入简单测试是为了对比公平。如果一个框架只在复杂交互上快,简单场景和对手差不多,和全程都更快,结论是完全不一样的。
智能筛选是首页的可收起侧边栏,一个带 CSS 动画的组件,点击头部就展开或收起,显示 / 隐藏分类和价格筛选控件。测试先点击展开,断言筛选可见;再点击收起,断言隐藏。
这个测试测的是框架处理 JS 驱动 UI 状态变化的速度。它也是 worker 数量增加后,表现最反常的一项 —— 后面会详细说。
Selenium 套件基于 RSpec 运行,使用selenium-webdriver gem,通过 ChromeDriver 驱动有界面的 Chrome 实例。
测试单进程串行执行 ——RSpec 默认不支持并行,也没有配置 Selenium Grid 或者外部并行执行器。
每个测试用独立的浏览器会话,用例内部完成打开和关闭。自定义的ResultsLogger会在每个用例结束后,把单测耗时和时间戳写入 CSV 文件。
套件执行命令:
总运行时长由 RSpec 在执行结束后输出。
Playwright 套件使用专门的对比配置playwright.comparison.config.ts,包含两个项目:
单测耗时取自 JSON 报告的duration字段(单位毫秒),仅统计测试本体执行时间,不含测试间开销。总墙钟时间来自同一份报告的stats.duration。
Playwright 测试采用了前一篇文章提到的 PCOM 架构,所有元素交互都走带类型的页面对象方法,不直接调用原始的page.locator()。Selenium 测试也使用了类似的页面对象模式。
最公平的正面较量,是串行执行的 Selenium,和同样 1 个 worker、同样测试顺序的 Playwright 对比。这样可以排除并行效应,只看纯框架开销的差异。
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
整套测试整体提速 1.16 倍,提升真实但幅度有限 —— 处于 “串行 Playwright 比 Selenium 快 1.5–2 倍” 预期范围的偏低区间。
原因主要有两点:测试里包含大量导航和服务端操作,这部分应用响应时间的权重远高于框架开销;另外 Playwright 有 Selenium 没有的初始化开销 —— 对比测试前要先跑种子项目。
分开看每个测试项,结果要更有意思。
简单场景的结果基本符合预期。AUTH-02 提速 2.69 倍,正好对应 Playwright 自动等待架构的优势:Selenium 要显式写wait.until(element_to_be_visible)等错误元素出现,这部分额外开销,Playwright 的断言重试机制直接就消掉了。
PD-01 提速 1.57 倍、SF-04 提速 1.25 倍,体现了 Playwright 持久 WebSocket 连接的低延迟优势 —— 对比 Selenium 每条命令都走一次 HTTP 的 WebDriver 协议,优势稳定存在。
AUTH-01 提速 1.13 倍、CART-01 提速 1.07 倍,提升就很小了。这两个测试的耗时主要在服务端往返,不是框架操作,框架能优化的空间自然就被压缩了。
商品网格测试 Selenium 要 16.69 秒,Playwright 只要 3.84 秒 —— 这个差距单靠框架协议差异解释不完。三个因素叠加在一起放大了差距:
三个因素叠加,结果看起来差距悬殊,但每个影响项都是真实存在的。这也说明“框架开销” 不是一个固定数字 —— 它是乘数效应,测试里元素交互越多,叠加越明显。
结算导航测试是唯一一个 Playwright 比 Selenium 稍慢的项(7.93 秒 vs 7.78 秒,差 150 毫秒)。单次运行看这个差值在误差范围内,但依然值得注意。
CHK-01 串联两次已登录的 APEX 导航:首页→购物车→结算。每次导航都要 APEX 验证会话、生成页面、触发 JS 页面加载生命周期,测试才能继续。
当测试几乎全由服务端响应时间主导时,Playwright 的框架开销优势就消失了 —— 而且 Playwright 的等待策略是等页面达到完全可交互状态,在服务端很快、元素交互极少的场景下,等待时间可能比 Selenium 基于 URL 的断言稍长一点。
这就是基准测试资料里常说的 “收益极小” 场景:测试耗时主要看应用响应速度,不是自动化开销,框架能发挥的空间本来就很小。
未完待续

