介绍一下我们测试人员编写自动化的时候两个常用的库优缺点Playwright vs Selenium

Selenium:自动化界的“老黄牛”

Selenium 诞生于 2004 年,是自动化测试领域的绝对霸主,它的优缺点都源于它的“资历”。

优点:

  1. **无可比拟的兼容性(最大优势):**​ Selenium 支持几乎所有的主流浏览器(Chrome、Firefox、Safari、Edge,甚至老旧的 IE)和操作系统。如果你的项目需要测试古老的 IE 浏览器,Selenium 是唯一的选择。
  2. **语言支持最广:**​ 它支持 Java、Python、C#、JavaScript、Ruby、PHP 等几乎所有主流编程语言。无论团队的技术栈是什么,都能无缝接入 Selenium。
  3. **生态成熟,资料丰富:**​ 经过近 20 年的积累,Selenium 拥有庞大的社区。遇到任何报错,几乎都能在网上搜到解决方案。它与 Appium(移动端自动化)同源,理念互通,便于扩展。
  4. **企业级支持:**​ 许多传统大型企业的老项目,其测试框架底层都是基于 Selenium 构建的,相关的 Jenkins、Grid 集群等基础设施非常完善。

缺点:

  1. **稳定性差(最头疼的问题):**​ Selenium 在执行时经常因为页面加载慢、网络波动而出现“元素找不到”的错误。为了保证脚本不崩,测试人员必须写大量的 sleep(强制等待)或复杂的“显式等待”代码,这让脚本变得臃肿且难以维护。
  2. **速度慢:**​ Selenium 通过 HTTP 协议与浏览器驱动(WebDriver)通信,中间环节多,就像寄信一样一来一回,执行速度相对较慢,尤其是在大规模并发执行时。
  3. **配置繁琐:**​ 需要手动管理浏览器驱动版本(虽然现在有 Selenium Manager 改善了,但历史上这是个很大的坑),环境搭建对新手不够友好。
  4. **调试困难:**​ 脚本跑失败了,通常只能看到一张截图和一堆报错日志,很难还原当时的页面状态(比如 DOM 结构变化过程),排查问题像“破案”。

Playwright:新时代的“智能刺客”

Playwright 由微软推出,专为现代 Web 应用(React/Vue/Angular)设计,它的优缺点正好针对 Selenium 的痛点。

优点:

  1. **极高的稳定性(杀手锏):**​ Playwright 内置了“自动等待”机制。它在点击或输入之前,会自动检查元素是否可见、可交互、且处于稳定状态。这意味着你几乎不需要写等待代码,脚本“脾气”很好,不容易因为网络慢而报错。
  2. **执行速度快:**​ 它使用 WebSocket 协议与浏览器内核直接通信,像打电话一样实时传输指令,加上浏览器上下文(Browser Context)复用技术,启动和执行速度远超 Selenium。
  3. **开箱即用:**​ 安装时一条命令就能自动下载匹配的浏览器和驱动,无需担心版本兼容问题。自带强大的 CodeGen(录制工具)和 Trace Viewer(追踪工具),调试时可以像看视频一样回放测试过程,精准定位问题。
  4. **强大的现代特性:**​ 原生支持拦截网络请求(Mock 数据)、模拟地理位置、权限(如通知)以及移动端视口。它对处理复杂的 iframe、Shadow DOM 和文件下载上传也非常优雅,无需像 Selenium 那样切换上下文。

缺点:

  1. **不支持老旧环境:**​ Playwright 不支持 Internet Explorer (IE)。如果你的客户还在用 IE,那就告别 Playwright 吧。
  2. **无法测试原生移动 App:**​ Playwright 只能模拟移动端的浏览器环境(H5),不能像 Appium 那样去控制手机上的原生 App(如微信、抖音客户端)。
  3. **生态相对年轻:**​ 虽然发展迅猛,但毕竟发布较晚,在遇到一些非常冷门、奇葩的浏览器行为或企业级定制化需求时,可能不如 Selenium 那样有现成的轮子可用。
  4. **语言支持略少:**​ 虽然也支持主流语言,但对于 Ruby、PHP 等小众语言的支持力度远不如 Selenium。

总结性的比喻

  • Selenium​ 像一辆手动挡的老吉普车。它能去任何地方(兼容性强),修车铺遍地都是(资料多),但是开起来很累,需要时刻踩离合(写等待代码),容易熄火(脚本报错)。
  • Playwright​ 像一辆顶配的自动挡特斯拉。开起来很爽,基本不用操心换挡(自动等待),有全景影像辅助(Trace Viewer),跑得飞快。但是它不能下深沟烂路(不支持 IE),也不能开出公路去越野(不能测原生 App)。

**目前的行业趋势是:**​ 新项目、Web 项目、追求效率的团队首选 Playwright;维护老项目、需要测 IE 或原生 App 的团队继续使用 Selenium。

需要我为你梳理一份从 Selenium 迁移到 Playwright的注意事项清单,或者帮你分析如何向团队推荐引入 Playwright吗?

我们使用代码简单看一下两者之间的差距

测试目标

  1. 打开登录页
  2. 输入用户名和密码
  3. 点击登录
  4. 验证登录成功后的欢迎信息
  5. 处理可能出现的“验证码弹窗”(模拟真实世界的干扰)

首先来看selenium:


import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.common.exceptions import TimeoutException, NoSuchElementExceptionfrom selenium.webdriver.chrome.service import Servicefrom webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))driver.maximize_window()

driver.get("https://example.com/login")


# 3. 显式等待元素出现(Selenium必须写,否则容易报错)
wait = WebDriverWait(driver, 10)

# 4. 定位元素并操作
username_input = wait.until(EC.visibility_of_element_located((By.ID, "username")))
username_input.send_keys("admin")

password_input = wait.until(EC.visibility_of_element_located((By.ID, "password")))
password_input.send_keys("123456")

# 处理可能的干扰(例如:随机出现的广告或弹窗)
try:
    close_btn = driver.find_element(By.CSS_SELECTOR, ".modal-close")
    close_btn.click()
    print("关闭了干扰弹窗")
except NoSuchElementException:
    pass # 没找到就算了

# 5. 点击登录
login_button = wait.until(EC.element_to_be_clickable((By.ID, "loginBtn")))
login_button.click()

# 6. 断言(必须等待结果出现)
welcome_text = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "welcome")))

assert "Welcome" in welcome_text.text
print("测试通过!")
except TimeoutException:print("测试失败:元素加载超时")driver.save_screenshot("selenium_error.png")

finally:# 7. 清理time.sleep(2) # 强制等待2秒看结果driver.quit()

再来看一下Playwright

pip install playwright

playwright install

from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeoutError

with sync_playwright() as p:# 1. 初始化(自动下载和管理驱动)browser = p.chromium.launch(headless=False, slow_mo=1000) # slow_mo便于观察page = browser.new_page()
# 2. 导航
page.goto("https://example.com/login", timeout=60000)

# 3. 操作(Playwright 内置自动等待,无需显式写 wait)
# 它会自动等元素可见、可点击、稳定
page.fill("#username", "admin")
page.fill("#password", "123456")

# 4. 处理干扰(Playwright 的 Locator 机制更稳健)
# locator 是“弹性”的,如果元素不存在,不会立即报错,除非你强制操作
close_btn = page.locator(".modal-close")
if close_btn.is_visible():
    close_btn.click()
    print("关闭了干扰弹窗")

# 5. 点击登录
page.click("#loginBtn") 

# 6. 断言(Playwright 自带的 expect 断言库,包含自动重试逻辑)
# 即使网络慢,它会一直尝试直到超时,而不是立刻失败
expect(page.locator(".welcome")).to_contain_text("Welcome", timeout=10000)
print("测试通过!")

# 7. 清理
browser.close()