告别Selenium痛点:这8款自动化工具让你省心不止一点

发布时间:2026/9/5 1:46:17
告别Selenium痛点:这8款自动化工具让你省心不止一点 先说一个我自己的真实体验有段时间我维护的 Selenium 脚本比业务代码还多。每次跑回归第一件事不是看测试结果而是去改find_element的等待条件和switch_to逻辑。页面稍作改版脚本就碎成一片。后来我陆续试了 8 款自动化工具才意识到大部分痛点根本不是“脚本水平不够”而是 Selenium 这套架构和心智模型已经跟不上现在网页的动态渲染节奏。如果你也写过 Selenium 脚本用过 WebDriverWait被 element not interactable 折磨过这篇文章会很对你的胃口。这里推荐的 8 款 Selenium 替代工具覆盖了编程型、低代码型、以及图形识别型三条路线。你可能是测试工程师想替团队找一个更好维护的自动化测试框架也可能是爬虫开发者想跳出 Selenium 的高脆性去采集动态页面还可能是只是想把日常重复的网页操作变成脚本的普通用户。不同的人适合不同的工具我会把每款工具的适用场景、实测感受、踩坑点都讲清楚方便你直接用起来。1. 先搞明白Selenium 脚本到底“低效”在哪里1.1 写测试脚本最心累的几个瞬间Selenium 本身是一个很成熟的 WebDriver 协议实现它最大的价值在于把浏览器操作标准化让 Python、Java、C# 这些语言都能通过同一套 API 去驱动 Chrome、Firefox、Edge。但也正因为太“通用”它对脚本编写者的要求相当高。最常见的低效是等待条件动态页面里元素不是同时出现的你往往需要在关键步骤前写WebDriverWait(driver, 10).until(EC.presence_of_element_located(...))。一次两次还好脚本一多几乎每一行核心操作前都要加等待代码瞬间变成一堆模板嵌套。另一个让人崩溃的地方是定位策略。Selenium 时代的经典写法是driver.find_element_by_xpath为了精确定位很多人直接复制浏览器里的完整 XPath。结果就是元素层级一变脚本就死。加上 iframe、多标签页、shadow DOM 这些现代前端特性每一步都是额外的switch_to和上下文切换成本。写脚本原本是为了省时间结果大部分时间都花在了“让脚本能跑起来”上。还有一点容易被忽略Selenium 本身不自带浏览器你必须自己维护 Chromedriver、Geckodriver 这类驱动。浏览器升级后驱动版本不匹配CI 环境里裸奔的机器动不动就报 session not created。这个问题虽然可以用 WebDriverManager 缓解但它只是把“手工下驱动”变成了“依赖拉驱动”并没有真正消除驱动这层脆弱性。1.2 新一代替代工具的共性把“等浏览器”交给工具我推荐的这 8 款工具多多少少都在解决上面那几类问题。它们的共性是默认自动等待、自带浏览器管理、调试体验更好。比如 Playwright 和 Cypress元素操作之前会自动等待元素可见、可点击不需要你再写一堆 expected conditionPuppeteer 通过 Chrome DevTools 协议直接跟浏览器内核通信绕开了 WebDriver 的会话模型TestCafe 甚至不需要浏览器驱动启动时会自己读取本机浏览器并注入控制脚本。更关键的是这些工具把“用户操作意图”变成了一等公民。你不需要关心底层是 XPath 还是 CSS只需要告诉工具“登录按钮点一下”也不需要自己处理页面跳转带来的导航等待因为工具知道点击后可能发生导航会内部自动等待。这种设计思路带来的直接收益就是脚本更短稳定性更高阅读起来也更接近自然语言。这正是项目标题里说的“更省事”。2. 先看清分类再选型避免“为了替换而替换”2.1 按代码量分为三大流派不是所有场景都需要写一堆代码。从实战角度我建议把 8 款工具分成三个流派。第一派是编程型工具代表是 Playwright、Puppeteer、Cypress、WebdriverIO、TestCafe、Taiko它们适合有编程基础的人和需要深度定制的场景。第二派是低代码/无代码工具代表是 Automa适合 Quick Task 和普通办公人员。第三派是图像识别工具代表是 AirTest它面向的是 Android、Windows、游戏这类不方便拿到 DOM 树的场景。很多人一听到“Selenium 替代”就下意识在 Playwright 和 Cypress 之间二选一其实没必要。如果公司已有的安全合规、发布流程深度绑定 Selenium Grid你可以用 WebdriverIO 继续跑 WebDriver 协议但换来更好的开发体验。如果你做的事情是“每天定时在网页上抓几张报表”用 Automa 拖拽几下就行不需要进入 Node.js/Python 的世界。选型前先把要解决的问题写清楚否则容易从一个坑跳到另一个坑。2.2 按落地场景确认优先级我这里给出一张可以照抄的场景对照表后面每个小节的细节都会围绕它展开。做 Web UI 自动化回归测试首选 Playwright 或 Cypress爬动态网页但页面交互复杂首选 Playwright只需要 Chrome 且想写尽量少的代码Puppeteer 足够已有 Selenium Grid 资产或团队以 Java 为主WebdriverIO 比 Selenium 原生更友好想完全不碰驱动配置TestCafe 最无感想要测试脚本像黑盒用户操作一样好读Taiko 值得试手机 App、游戏、设备老化测试这类非浏览器对象AirTest 是更合适的答案只想给自己省点重复点击Automa 一个浏览器扩展就能搞定。场景首选备选主要原因Web 自动化测试PlaywrightCypress / TestCafe自动等待稳定多浏览器覆盖动态页面爬虫PlaywrightPuppeteer可拦截网络请求等待机制强前端快速回归CypressPlaywright实时刷新和调试体验极好兼容现有 GridWebdriverIOSelenium 4保持 WebDriver封装现代无驱动开箱即用TestCafePlaywright不需要安装浏览器驱动黑盒用户式测试TaikoCypressAPI 贴近自然语言游戏/设备老化AirTest无基于图像识别拿不到 DOM零代码日常自动化AutomaAirTest拖拽块即可扩展轻量3. 编程型首选Playwright、Puppeteer、Cypress 详细拆解3.1 Playwright目前最接近“写完就能稳定跑”的工具Playwright 是微软开源的工具支持 Chromium、Firefox、WebKit 三种内核Python 和 JavaScript/TypeScript 都有官方 SDK。它最大的卖点是“自动等待”。比如你用page.click()它会先等元素出现在 DOM 里再等元素可见、稳定、接收事件一套流程内置完成不再需要显式 sleep 或 WebDriverWait。这种等待不是简单轮询而是基于浏览器内部的事件驱动效率比 Selenium 的固定轮询高很多。拿登录场景做个直观对比。Selenium 的风格是from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver webdriver.Chrome() driver.get(https://example.com/login) username WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, username)) ) username.send_keys(demo) password WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, password)) ) password.send_keys(123456) driver.find_element(By.ID, submit).click() driver.quit()同样的用例用 Playwright 写出来会短一截from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessFalse) page browser.new_page() page.goto(https://example.com/login) page.fill(#username, demo) page.fill(#password, 123456) page.click(#submit) browser.close()从上手体验看Playwright 也更省心安装后执行playwright install就能自动下载匹配的内核版本不再需要担心 Chromedriver 和 Chrome 版本不一致。它在多标签页、iframe、下载文件、网络请求拦截这些场景下都提供了高级 API。比如拦截图片请求可以用page.route这在网页爬虫里非常实用能让脚本关掉无用的图片资源大幅提升采集速度。我在实际项目里用 Playwright 重写了一套老 Selenium 回归用例用例数量从 120 个减少到 90 个左右因为原来的很多前置等待步骤都直接删掉了而通过率反而从 85% 提到了 98% 左右。如果非要说 Playwright 的缺点它对测试报告的集成不像 Cypress 那么“开箱即美”需要自己搭 HTML report 或接入 Allure。另外它的 API 设计是 event-driven 风格初次接触的人容易搞混sync_playwright和async_playwright两种模式。不过这些都只是学习成本不是硬伤。我遇到过最坑的是在企业内部网络环境下运行playwright install时浏览器二进制包下载被网络策略挡掉解决办法是把下载地址换成内网镜像或者手动放置浏览器到指定缓存目录。3.2 Puppeteer只在 Chromium 生态里干活时最轻量Puppeteer 是 Chrome DevTools 团队出品的 Node.js 库通过 DevTools Protocol 控制浏览器。它并不像 Selenium 那样支持各厂商浏览器主战场就是 Chromium 系。好处是协议非常底层浏览器能力几乎全量暴露性能开销也小。如果你要做批量截图、PDF 生成、预渲染、抓取 SPA 页面数据Puppeteer 往往是比 Selenium 更刀刃向内的选择。Puppeteer 的代码风格和 Playwright 有相似之处但更依赖 Node.js 的事件循环。下面是登录示例const puppeteer require(puppeteer); (async () { const browser await puppeteer.launch({ headless: false }); const page await browser.newPage(); await page.goto(https://example.com/login); await page.type(#username, demo); await page.type(#password, 123456); await Promise.all([ page.waitForNavigation(), page.click(#submit) ]); await page.screenshot({ path: after-login.png }); await browser.close(); })();这里有个小技巧点击按钮触发页面跳转时最好把waitForNavigation和click放在同一个Promise.all里避免点击之后的竞态。Selenium 时代很多人会直接加 sleep但在 Puppeteer 里用导航等待事件更优雅。Puppeteer 还提供了page.waitForSelector、page.waitForResponse等细粒度等待比固定 sleep 可靠得多。Puppeteer 的局限是如果你需要覆盖 Firefox、Safari它并不合适。同时因为协议是 Deep Link 到 Chromium某些企业定制浏览器的兼容性也需要额外验证。我自己的实践建议是爬虫和截图任务优先上 Puppeteer因为它生态里的puppeteer-cluster这类并发库很成熟能轻松实现带并发控制的批量抓取但如果是跨浏览器自动化测试还是把重心放回 Playwright 或 Cypress。3.3 Cypress前端测试体验最惊喜但适用边界要清楚Cypress 跟前两者走的是不同路线。它把测试代码运行在浏览器内部而不是像 Selenium 那样从外部进程用 WebDriver 连接浏览器。这样一来Cypress 可以直接感知到页面里的异步加载、路由跳转和网络请求也能在浏览器开发者工具里实时看到每一步操作前后的状态俗称 time-travel 调试。对做前端页面回归的人来说这种体验几乎是碾压级的跑完测试可以直接点开每一步的截图看看到底是哪一步出了问题。一个典型写法如下describe(login spec, () { it(登录后跳转首页, () { cy.visit(https://example.com/login); cy.get(#username).type(demo); cy.get(#password).type(123456); cy.get(#submit).click(); cy.url().should(include, /home); }); });Cypress 的自动等待同样内置。cy.get(#submit)会等元素出现.click()会等元素可交互测试失败时默认自动截图和录视频。最关键的是它不需要 WebDriver也不需要 Selenium Grid 那种 node 注册机制一条npm install就能跑。很多前端团队把 Cypress 当作“提测前的自测脚本”因为它能直接在本地开发环境跑还能和 GitHub Actions、Jenkins 集成。但我要提醒你Cypress 有一个频繁踩坑的边界它历史上不支持多标签页和跨域 iframe 的天然操作虽然新版逐步在改善但一旦项目大量使用跨子域页面跳转或复杂 iframe你的脚本仍然会绕不少弯路。另外因为代码在浏览器内执行它不太适合操作浏览器窗口之外的东西比如原生系统弹窗、下载文件的系统级后续处理。所以我通常把 Cypress 定位成“前端测试专用”如果目标是做爬虫或系统级自动化不建议选它。实际用下来Cypress 最大的痛点反而是安装时下载二进制文件慢需要配置CYPRESS_DOWNLOAD_MIRROR或者在内网放置缓存其他开发体验基本不让人失望。4. 迁移友好派和自然语言派WebdriverIO、TestCafe、Taiko4.1 WebdriverIOSelenium Grid 的老用户不必推倒重来很多测试团队早就自建了 Selenium Grid不是因为它好用而是历史资产都在里面。这时候硬换 Playwright 会导致底层基建全部重写风险大。更平滑的方案是继续用 WebDriver 协议但把脚本框架从原生 Selenium 替换成 WebdriverIO。它本质上是基于 WebDriver 的 Node.js 测试框架但封装度远高于 Selenium 的 Java/Python API自带waitForClickable、waitForDisplayed这类语义化方法。示例代码describe(login test, () { it(应该能登录成功, async () { await browser.url(https://example.com/login); await $(#username).setValue(demo); await $(#password).setValue(123456); await $(#submit).click(); await expect($(.user-info)).toBeDisplayed(); }); });WebdriverIO 在原有 Selenium Grid 上可以直接运行只要把 npm 依赖和配置文件替换一下即可。它还有一大类插件体系比如wdio/allure-reporter、wdio/sauce-service以及外部云测服务集成能力。对 Java 团队来说虽然 WebdriverIO 是 JavaScript 技术栈但它带来的收益是代码量显著减少。这里有个选型上的心得如果你所在团队的脚本是 Java TestNG Selenium建议先不要无脑迁移到 WebdriverIO除非团队已经准备把测试代码统一成 JavaScript/TypeScript。否则你只会把原来 Java 的Test换成 JS 的it解决不了根本问题。更合理的路线是保留现网 Grid新用例用 Playwright 的官方connectOverCDP去连远程 Chrome逐步把老用例替换掉。WebdriverIO 适合本来就愿意用 Node.js 的人。4.2 TestCafe一条命令就能跑不用驱动也不用等环境TestCafe 有一个非常吸引人的特点不需要为浏览器安装驱动。它启动时会自动识别本机安装的 Chrome、Firefox、Edge、Safari然后通过一个内置的代理服务把自动化脚本注入页面。对 CI 环境尤其友好因为只要镜像里装了浏览器TestCafe 就能跑不用额外处理 WebDriver 版本问题。另一个优点是它原生支持并行测试不用再自己写多线程或进程池。TestCafe 的测试文件更适合业务人员阅读。用 JavaScript 写核心 API 手感不错import { Selector } from testcafe; fixture(登录测试) .page(https://example.com/login); test(登录后显示用户信息, async t { await t .typeText(#username, demo) .typeText(#password, 123456) .click(#submit) .expect(Selector(.user-info).visible).ok(); });TestCafe 也内置了自动等待Selector在找不到元素时会反复重试但你可以设置timeout参数来控制最长时间。它还有一个亮点是测试完成后自动产出 HTML 报告页面截图和视频也都能集成进去对要交付测试报告的团队非常实用。不过TestCafe 的生态和社区活跃度不像 Cypress 和 Playwright 那么高遇到复杂问题时不那么容易搜到答案。它早期版本的 iframe 处理也比较绕需要iframe选择器和switchToIframe方法不建议在非常依赖嵌套 iframe 的页面上使用。如果你只是想快速跑一个跨浏览器烟雾测试TestCafe 的省事程度确实排得上前列。4.3 Taiko让脚本读起来像“用户操作说明书”Taiko 是 ThoughtWorks 团队开源的一个 Node.js 自动化库整体设计思路比较独特你不需要写 CSS 或 XPath而是用“写在这、点击那个”这样的层级来定位元素。比如登录页面既没有稳定 id 也没有>const { open, write, into, click, textBox, button, closeBrowser } require(taiko); (async () { await open(https://example.com/login); await write(demo, into(textBox({ placeholder: 用户名 }))); await write(123456, into(textBox({ placeholder: 密码 }))); await click(button(登录)); await closeBrowser(); })();Taiko 也内置了等待和无头模式并且有配套的录制器。你可以在终端启动taiko操作浏览器后自动生成脚本这比 Selenium IDE 生成的脚本要干净得多。Taiko 这个工具的定位很适合“从黑盒测试角度做用例维护的人”它不关心页面内部结构只关心角色和行为。不过要注意正因为不依赖传统选择器Taiko 在页面变化频繁的情况下会面临定位不稳定。比如按钮文字从“登录”改成“立即登录”脚本可能就识别不了。它的做法是检查可访问性文本所以如果产品文案经常改还是需要用带aria-label的元素提供稳定锚点。实际我用的体验是Taiko 更适合中小型项目或验证类任务不适合要做非常细粒度断言的平台级项目。5. 零代码图形识别路线AirTest 与 Automa5.1 AirTestAndroid、Windows 和游戏自动化中的一股清流AirTest 是网易开源的一款基于图像识别的自动化工具核心思路是“截屏找图”。在普通 Web 自动化里我们很少用这种方案因为 DOM 信息更准确但当你面对游戏 App、设备老化测试、Windows 桌面软件时元素树根本拿不到就必须靠图像识别。AirTest 最大的价值是提供了一套 Python API 和配套 IDE可以跨平台连接 Android、iOS、Windows 等设备进行点击、滑动、按键操作。一个典型的设备老化测试脚本长这样from airtest.core.api import * auto_setup(__file__) connect_device(Android:///) start_app(com.example.app) # 等待首页出现如果超过 120 秒则判定异常 if wait(Template(home_screen.png), timeout120): swipe((800, 1200), (800, 400)) touch(Template(start_task.png)) else: raise RuntimeError(设备老化测试启动异常)这个思路解决了一个 Selenium 完全无能为力的场景被测对象不是浏览器页面。你可以在设备上长时间挂机循环执行点击、滑动、截图比对记录设备是否存在卡死、ANR、掉线、画面残留等问题。热搜词里“设备老化测试全自动执行脚本”对应的就是这类需求。在写老化测试脚本时最忌讳的是每个动作间隔固定写死比如sleep(10)。设备性能波动时固定 sleep 很容易误判。AirTest 的wait(Template(...), timeout...)更适合用来判断某一画面是否在预期时间内出现。使用 AirTest 的常见坑是图像模板的清晰度。模板图片分辨率跟设备实际截图不一致时匹配率会下降。建议制作模板时从目标设备实际分辨率和 DPI 下截图不要拿网上随便找的图同时可以使用threshold0.8这类参数控制相似度阈值。它也不是万能药如果页面是多字节字体、真彩色渐变背景匹配率也会波动这时就要考虑加 OCR 插件。总体而言在非标准 UI 自动化这块AirTest 是 Selenium 之外的一个重要补充。5.2 Automa日常工作流自动化的“积木”如果你不是程序员看到前面这么多 Python/JavaScript 代码可能已经想关页面了。没关系Automa 就是为“不想写代码”的人准备的。它是一款浏览器扩展通过拖拽不同的“块”来搭建自动化流程打开网址、点击元素、填写输入框、循环列表、读取页面文本、下载文件等。整个工作流可以在浏览器里用可视化的方式编辑最后还能导出成 JSON 文件分享给别人。以“每天上班先打开数据后台把昨日订单数保存到本地”为例Automa 的流程大致是新建工作流添加“打开网页”块并填入后台地址添加“点击元素”块元素选择器可以用内置的拾取器点在登录按钮上添加“输入文本”块填入账号密码“延迟”块等待页面加载再添加“获取文本”块抓取订单数字最后用“写入文件”块保存到本地或通过“通知”块提醒自己。Automa 的优势是快适合临时性、低频率的个人任务。它也有定时触发、快捷键触发等能力还能在多个标签页间做处理。我常用它处理数据导出的小活不用下载一堆依赖。但它的限制同样明显跨域限制和浏览器安全模型仍然存在很多网站需要先人工登录一次Automa 再利用你的登录态去操作所以它不适合做完全无人值守的账号体系测试。在 Selenium 替代生态中Automa 属于典型的高频小工具能解决大量简单重复操作但上不了复杂系统的自动化测试台面。6. 从 Selenium 迁移到替代工具我的经验和建议6.1 迁移前先盘一盘“老脚本为什么难改”很多团队觉得迁移工具难其实难的不是 API而是前期没有清理老脚本里的坏味道。我之前接手过一套 Selenium 测试里面大量使用time.sleep(3)人员流动后没人知道为什么是 3 秒而不是 2 秒。这种脚本换成任何框架都还会出问题因为等待策略本身就是错的。所以迁移工具前我建议先把用例按三层分类第一类是高频且完整登录走主流程的用例优先迁移第二类是需要读写文件、操作非浏览器资源的用例后续再评估第三类是已经烂到没人维护、历史原因不明的用例直接删除或重写不要浪费迁移成本。同时要梳理公共操作比如登录、翻页、关闭弹窗、文件下载约定。这些公共操作在新工具里应该封装成独立模块。这一步比学新 API 更重要否则每个脚本还是各写各的迁移后依然是一团散沙。在我实际做的一次大迁移中花在整理旧用例上的时间大约是写新脚本时间的一半。这个准备阶段省不掉。6.2 用 Playwright 为例一步一步替换老脚本我拿一次典型迁移说明操作过程。第一步安装并初始化项目依赖Python 用pip install playwright playwright install chromiumNode.js 用npm init -y npm i -D playwright。第二步把 Selenium 脚本里的 WebDriver 等待全部删掉开始写 Playwright 的page.goto和page.locator通常元素定位优先使用get_by_role或 CSS不要再复制长 XPath。第三步用playwright codegen https://example.com打开录制器手动走一遍业务路径再把生成的脚本做简化。这里要说一个容易犯的错误有些人录完就开始跑结果录制的选择器在下次页面加载时依然不稳定。原因是录制器默认会生成偏向可访问性的aria选择器但某些框架生成的动态 id 会让选择器看起来很长。我更推荐在录制完以后手动给关键元素加上稳定标记比如>