资讯动态

Playwright自动化测试入门:从安装到高效用例编写全攻略

发布时间:2026/9/26 7:15:38 来源:尧图企业网站定制
今天想聊一个被问了很多次的话题Playwright。身边经常有想转自动化测试、或者已经在做手工测试想提升效率的朋友问我自动化测试框架那么多Selenium、Cypress、Appium为什么偏偏要选Playwright我的回答通常很简单如果你是从零开始Playwright是当下综合门槛最低、踩坑最少、回报最快的一个。它不需要你熟悉复杂的WebDriver协议不需要为浏览器驱动版本不匹配折腾半天也不需要写一堆额外代码去处理等待和重试。装好、写几行脚本浏览器就自动跑起来了。这篇文章就是写给那些准备迈出自动化测试第一步的人。我会把从安装环境到写出第一个测试用例的过程完整走一遍顺便把那些官方文档里写了但没说透、或者根本没人告诉你的细节也讲清楚。无论你是测试工程师、开发工程师还是产品经理想自己搭个冒烟测试看完这篇应该都能上手跑起来。1. 为什么把第一个自动化测试框架选在Playwright1.1 和Selenium相比Playwright到底赢在哪很多人的自动化测试入门都是从Selenium开始的这确实是老牌框架生态大、资料多。但用过一段时间后你会发现Selenium的很多痛点并不仅仅是“练习不够”造成的。比如WebDriver环境配置Selenium需要ChromeDriver、geckodriver这些单独的驱动文件而且驱动版本必须和浏览器版本匹配。浏览器一更新脚本可能就挂了你得先去下载对应驱动再改代码里的路径光是这一项就劝退了不少新手。Playwright的做法是自带浏览器内核管理。你执行一次playwright install它直接把Chromium、Firefox、WebKit三个内核都下到本地指定目录版本固定测试代码和浏览器内核是一起管理的。这就从机制上解决了“驱动不匹配”这类问题。即使你想用本机已经安装的Chrome它也能自动识别不需要单独下载驱动。另一个被大家频繁吐槽的点是等待。Selenium时代写UI自动化最经典的代码就是time.sleep(2)。但固定等待毫无逻辑——网络慢的时候2秒不够网络快的时候又白白浪费时间。Playwright内置了自动等待机制所有定位操作默认会等待元素可交互你不需要自己写sleep它会在元素出现、可见、可点击之后才执行下一步。这一步对于脚本稳定性的提升是巨大的。还有浏览器上下文隔离。Playwright里每个Browser Context相当于一个独立的隐身会话Cookie、缓存、Storage互相隔离。这意味着你可以在一个测试里只用一个浏览器实例但是跑多个互不干扰的场景并发效率比Selenium高很多。这个设计对测试工程师来说极其顺手后面我会专门讲。1.2 Playwright的核心设计思路是什么如果你用过Selenium再切到Playwright会明显感觉到它的API设计更加“懂测试”。Playwright所有操作都有一个默认超时时间默认是30秒而且所有操作的结果都是可等待的Promise在Python里就是自动同步阻塞。它的理念不是“你告诉浏览器干什么”而是“你描述期望的最终状态框架帮你等到达成”。举个例子你想点击某个按钮。用Selenium的方式你需要先find_element再检查is_displayed再可能调用WebDriverWait写一个expected_condition然后才click()。用Playwright的方式一条page.click(text提交)就搞定。它会自动等待按钮出现在DOM里等待它可见且不被遮挡等待它处于可点击状态再进行操作。如果超时还找不到报错信息里会告诉你当前页面大概是什么样、元素卡在哪一步。这种设计思路也影响了定位方式。Playwright推荐使用偏向用户视角的定位器比如文本、角色、标签而不是极长的XPath。原因很简单页面结构重构的频率远高于文案和语义变化面向用户可见的内容定位脚本的健壮性会好很多。1.3 这套框架真正适合解决什么问题从实用的角度说Playwright适合几种典型场景。一是Web UI自动化回归测试。这是主流用途页面反复迭代人工回归耗时巨大用Playwright写一套核心路径脚本每个版本发布前跑一遍能省下大量时间。二是端到端测试也就是E2E。Playwright可以直接启动真实浏览器模拟用户操作完整业务链路比如注册、登录、下单、支付。它甚至能拦截网络请求、模拟弱网、捕获接口响应这种能力是很多接口测试工具做不到的。三是爬虫和网页数据采集。这个领域你可能看到过“Playwright动态iframe”“Scrapy Playwright”这些关键词。因为很多页面数据是异步加载的直接用Requests拿不到内容而Playwright能渲染完整页面后再抓取简单粗暴地解决“页面数据是JS渲染出来的”问题。四是作为自动化测试基础设施。Playwright可以和pytest、Allure这些工具深度集成既有断言库也能生成HTML测试报告Jenkins、GitLab CI里都能跑。也就是说它不只是给个人调试用的玩具完全可以作为团队测试体系的基础。一句话总结只要是需要“打开一个真实浏览器去操作网页”的任务Playwright基本都能覆盖。2. 环境准备与最小运行路径2.1 Python环境的准备先说明一下语言选择。Playwright官方有JavaScript/TypeScript版和Python版两个都对。国内测试圈用Python的更多因为上手快、生态好、和pytest无缝衔接下面我就以Python版为主线来讲。你需要一个Python 3.8以上的环境。这里踩过的一个坑是系统里可能同时存在多个Python版本如果用Windows建议直接把Python安装路径加到系统环境变量里命令行输入python --version确认版本。如果是Mac或者Linux按系统自带的Python 3来用就行最好再建一个虚拟环境。创建虚拟环境是我个人非常推荐的第一步不然将来项目依赖多了包冲突会让新手崩溃。python -m venv venv source venv/bin/activate # Windows上请执行 venv\Scripts\activate激活后命令行前面会出现(venv)这表示你已经进入独立的Python环境了。后面所有安装的包都会在这个环境里互不干扰。2.2 安装Playwright和浏览器内核安装Playwright本身很简单pip一次搞定。pip install playwright注意这里有个小细节装完pip包之后你还得执行一条命令下载浏览器内核很多人卡在这一步。playwright install chromium如果你只需要测试Chrome系内核只装Chromium就够了。需要测试Firefox或者Safari渲染再装对应的浏览器。默认情况下这条命令会下载三个内核如果你不想全装可以只指定一个速度会快很多。我遇到过下载速度特别慢的情况。如果发现playwright install chromium卡住不动最简单的办法是配置国内镜像环境变量# Linux/Mac export PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright/ # Windows PowerShell $env:PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright/再执行下载命令就快多了。另外强调一点如果你本机已经装了Chrome或者EdgePlaywright也可以直接复用系统浏览器不需要下载内核。在启动浏览器时写channelchrome即可某些企业内网环境不能随意下载内核时这个参数很好用。2.3 第一个能跑起来的脚本先不看测试框架直接从最原始的脚本开始让你直观感受Playwright的执行方式。新建一个文件first_run.py内容如下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) print(页面标题是, page.title()) browser.close()在激活的虚拟环境里执行python first_run.py你会看到Chromium窗口打开加载页面打印标题后自动关闭。这个最小脚本里包含了全部的核心步骤启动浏览器、新建标签页、跳转URL、获取页面信息。如果改成无头模式把headlessFalse换成headlessTrue浏览器就会在后台静默运行适合挂在服务器上跑自动化任务。这里多说一个经验调试阶段一定用有头模式肉眼看得到每一步执行情况真正跑回归用例的时候再切成无头模式减少资源占用。新手上来就用无头模式页面出问题了很难定位。3. 核心细节解析与实操要点3.1 同步API和异步API选哪个Playwright的Python版提供了两套API入口sync_playwright和async_playwright。同步版写起来就是从上到下一行行执行心智负担很小新手/大多数测试脚本用同步版就够。异步版是配合asyncio用的适合在已有异步项目中调用或者高并发场景下追求更优资源利用率。我自己写常规回归用例时一直用同步版逻辑清晰、调试方便。除非你要在同一个Python进程里并发跑几十个浏览器实例、对性能有比较高的要求再去考虑异步。一个常见的认知误区是写脚本时用了asyncio就一定会更快。其实对于单页面线性操作异步并不一定比同步快多少反而会让新手陷入“协程没挂起”“时间循环没跑”之类的坑。初学阶段别纠结这个先把同步版跑通。3.2 定位元素的方法从CSS到文本定位自动化测试绕不开定位元素Playwright的locator机制是它的核心优势之一。它不像Selenium那样把“找到元素”和“操作元素”分得很开而是先声明一个locator后续可以反复使用。常用的定位语法我列一下page.locator(#username) # CSS id选择器 page.locator(input[nameemail]) # CSS 属性选择器 page.locator(text登录) # 按可见文本定位 page.locator(button:has-text(提交)) # 按钮包含某段文本 page.get_by_role(button, name提交) # 按角色定位更贴近用户视角Playwright官方最推荐的是get_by_roleget_by_label这组“用户视角”定位器。比如表单输入框通常有对应的label文字page.get_by_label(用户名)就能自动命中。这样写的好处是前端调整CSS类名、DOM结构时测试代码基本不用改。至于XPath能不用就不用。XPath在DOM大改后很容易失效而且不可读性极强。实在遇到复杂定位可以用XPath但在Playwright里也可以把XPath转成多条件组合定位健壮性更好。另外Playwright的locator有“严格模式”的概念。如果你写的locator命中了多个元素执行操作时默认会报错提示你匹配到多个节点、需要更精确的定位器。这可以有效避免脚本“不小心”点了错误的元素。如果的确想操作第一个匹配项可以显式用.first。3.3 自动等待机制为什么不需要手动sleep这是Playwright用起来和Selenium感受差别最大的地方。在Playwright里locator.click()等操作会自动执行“可操作性检查”包括这几个方面元素已附加到DOM、元素可见、元素是稳定的可以理解为不在抖动或移动中、元素接收事件不会被其他元素遮挡、元素是启用的。这些检查全部通过才真正执行点击。整个等待过程受超时时间控制默认30秒。所以大部分情况下你不再需要写time.sleep。刚开始切到Playwright的人脑子里还是“等一下再点”的老思路你会发现删掉sleep之后脚本反而更稳定了因为“等到可操作”比“固定等几秒”更科学。如果你想改变全局超时在启动浏览器或创建context时可以这样配置browser p.chromium.launch() context browser.new_context() page.set_default_timeout(15000) # 单页面操作超时改为15秒某些特殊场景你确实需要主动等待比如等待某个请求完成可以用page.wait_for_response()或者page.wait_for_timeout()。注意wait_for_timeout在这种场景本质上还是固定sleep能不用尽量不用官方甚至直接说明这是在“极其罕见”的场景下使用的。3.4 Browser Context让测试之间互不干扰Browser Context浏览器上下文是Playwright的一个核心概念。你可以把它理解为一个“隐身窗口”每个Context内部有独立的存储空间。在同一浏览器实例里可以创建多个Context它们之间Cookie、Token、LocalStorage完全隔离。这个特性对自动化测试有多重要举个例子你想跑两条测试用例一条验证登录用户可以下单另一条验证未登录用户点击下单会跳转登录页。如果用同一个Context前一条用例登录后的Cookie会污染后一条用例的状态。用Selenium你只能分别起两个浏览器实例代价是启动慢、资源占用高。用Playwright直接在同一个浏览器里开两个互不干扰的Context轻量且速度快。context1 browser.new_context() page1 context1.new_page() context2 browser.new_context() page2 context2.new_page()你也可以用context在测试开始时统一注入一些初始状态比如模拟移动端设备、设置地理定位、注入认证凭证。日常做测试隔离、性能优化、多账号并发Context都是最顺手的手段。4. 从脚本到测试用例完整实操4.1 用codegen快速生成定位器有基础业务经验的同学都知道页面元素定位是写UI自动化最耗时的一步。Playwright提供了一个录制神器codegen。它本质上是开一个浏览器窗口你在窗口里手动点击、输入文字、跳转页面它同步生成对应的Playwright脚本。执行方式很简单playwright codegen https://example.com浏览器窗口弹出后你先手动操作一遍流程比如点击登录、输入用户名密码、点击提交。每操作一步右边代码面板就会生成一行对应的Python代码。操作完把代码拷贝到项目里稍微整理就能用。这个工具的价值不仅仅在于录制。录制一段时间后再手工看生成的定位器写法你会很自然地学会Playwright推荐的定位策略。它甚至会自动用get_by_role这类语义化定位器来替换冗长的CSS选择器这比我当年手写XPath试错快多了。不过录制的代码通常会有很多冗余需要手工清理。比如录制时鼠标滑过页面会产生很多hover操作这些在回归测试里一般是不需要的我通常只保留关键操作和断言。4.2 pytest集成让脚本变成测试用例Playwright的脚本只是“能跑”而测试框架解决的是“怎么组织、怎么断言、怎么出报告”的问题。pytest作为Python生态里最流行的测试框架和Playwright配合非常自然。首先安装pytest插件pip install pytest-playwright这个插件会提供fixture让测试用例自动获取浏览器和页面对象。比如写一个测试文件test_login.pyimport re from playwright.sync_api import Page, expect def test_login_page_title(page: Page): page.goto(https://example.com/login) expect(page).to_have_title(re.compile(登录))page这个参数不需要你手动创建pytest-playwright会在每条用例前自动生成一个全新的浏览器Context用例结束后自动销毁。这也是上面说的隔离机制在框架层的体现。控制并发也很简单。pytest-playwright默认是串行跑但可以通过--workers参数启用多进程并发。注意每个worker会启动独立的浏览器实例用例越多提速越明显但消耗的内存也会成倍上升。4.3 断言怎么写更靠谱Playwright有自己的断言库expect。它和pytest自带的assert不同expect会自动重试直到满足条件或超时。这是UI测试中很关键的一点页面状态可能有一个短暂的异步变化过程用普通assert判断经常会偶现失败用expect则会等目标状态稳定后再通过。常用的断言写法from playwright.sync_api import expect expect(page).to_have_title(订单列表) expect(page.locator(.success)).to_be_visible() expect(page.locator(#toast)).to_contain_text(操作成功) expect(page.url()).to_contain(/orders)我写用例时习惯在完成关键操作后至少加一个页面级断言比如URL变化、标题变化、关键元素可见。这一步是在给后续维护者“兜底”防止页面改了但脚本还在闷头往下走。另外断言文案尽量断言用户能看到的文本不要断言CSS类名或者某个HTML属性那些太容易变化了。4.4 并行执行与Allure报告到了用例多起来的时候你会关心两件事能不能加速结果怎么看加速方面pytest-xdist插件可以实现多进程执行。命令大致是pytest test_login.py --workers 4需要注意并发执行时用例之间不要共享状态。好在Playwright的Context隔离机制已经保证了每个用例默认独立只要你不在用例外部去搞共享的全局变量基本不会串。结果报告方面Allure是目前最主流的方案。它能把每个步骤、截图、断言结果组织成美观的HTML报告。安装方式pip install allure-pytest运行用例时加一行--alluredirreport用例结束后再用Allure命令生成报告页面。如果测试失败Playwright会自动为失败场景截图这块配合Allure非常直观一眼就能看出是页面报错还是元素找不到。pytest test_login.py --alluredirreport allure serve report这里插一句Allure报告的美化和定制是后话但“失败有截图、有日志、有步骤”这个能力是自动化测试真正能落地到日常回归的必要条件。5. 常见问题与排查技巧实录5.1 元素定位不到最常见的原因是什么定位不到元素是新人遇到最多的报错报错类型大概是TimoutError或strict mode violation。前者表示等待超时后者表示匹配到多个元素。排查时我有一套固定流程。第一步先在有头模式下跑看看浏览器停在哪个页面URL对不对。很多时候是前置操作没生效导致页面根本没跳转。第二步检查是否在iframe里。网页中的登录框、支付弹窗往往在iframe中。Playwright默认只操作主页面frame不在iframe里的元素肯定是“消失”状态。你需要先切换进去frame page.frame_locator(#iframe-id) frame.locator(#username).fill(test)第三步检查元素是不是只在某种状态才存在。比如按钮要等接口返回后才渲染这时你应该用expect(locator).to_be_visible()去等状态或者使用locator.wait_for()显式等待。我提醒新人的一点是不要为了“压住”超时报错就去调大全局超时时间或者到处加wait_for_timeout。找到根因是iframe、是时机、还是定位器不够精确才是正路。5.2 处理弹窗、新开标签页和监听事件弹窗分两种浏览器弹出框和页面内弹窗。前者是alert/confirm/prompt这类原生弹窗Playwright有专门的监听方式page.on(dialog, lambda dialog: dialog.accept())页面内弹窗比如每个网站都有的“领取优惠券”浮层则建议优先尝试用文本定位直接关掉或者用page.locator(text关闭).click()处理。浮层是否弹出有时和定时器有关所以脚本里最好先判断它是否出现再处理不要一上来就点关闭按钮否则没弹窗时反而报错。新开标签页是点击target_blank链接时的经典坑点。Playwright中点击一个链接后新开标签页页面对象是新的你需要用context.expect_page()来捕获with context.expect_page() as new_page_info: page.click(text去第三方登录) new_page new_page_info.value new_page.wait_for_load_state()如果你不捕获这个新页面后续操作还用旧page那必然定位不到元素。监听网络请求是调试和断言的利器。你想确认某次点击是否触发了正确接口可以这样监听with page.expect_response(lambda response: /api/order in response.url) as resp_info: page.click(text提交订单) response resp_info.value assert response.status 2005.3 页面滚动、截图和下载文件页面滚动在实际项目中经常遇到比如“加载更多”按钮要滚动到页面底部才出现。Playwright提供了直接滚动的方案page.mouse.wheel(0, 5000) # 或 page.locator(#footer).scroll_into_view_if_needed()第二种更常用因为它的语义是“把这个元素滚动到可视区内”比盲目滚动到固定距离更精准。如果页面是无限下拉加载可以循环执行滚动直到目标元素出现再退出循环。截图是排查问题最直观的手段。整屏截图用page.screenshot(full_pageTrue)元素截图用locator.screenshot()。很多测试报告里会自动插入截图但我建议在关键操作节点主动埋几个截图点比如下单成功、支付成功将来出了bug对比截图定位速度会快很多。下载文件的处理也有固定套路。点击下载链接后需要用expect_download捕获with page.expect_download() as download_info: page.click(text下载模板) download download_info.value download.save_as(./files/template.xlsx)下载路径可以自己指定这个在自动化处理报表导出、文件上传校验的场景里非常实用。5.4 调试技巧trace、pause和慢动作调试Playwright用例我常用的三件套是trace、pause和slow_mo。--tracing选项会在测试运行时记录完整的步骤、DOM快照、网络请求和控制台日志。用例跑完你可以用playwright show-trace打开一个可视化的操作时间线一步步回放当时页面发生了什么。遇到偶现的失败报错这个trace几乎是救命稻草。想边调试边运行可以在代码里插入page.pause()脚本执行到这一行会暂停并自动打开Playwright Inspector此时你可以在浏览器里手动操作也可以在下方的控制台输入命令继续执行。跑调初期用它逐步查看运行状态很舒服。慢动作是在启动浏览器时加一个参数browser p.chromium.launch(headlessFalse, slow_mo500)slow_mo500表示每个操作之间隔500毫秒适合观察脚本执行过程到底卡在哪个环节。5.5 常见问题速查表现象常见原因解决思路元素找不到超时30秒元素在iframe里 / 元素加载缓慢 / locator写得不精确检查iframe使用frame_locator用expect等待增加定位依据click无效不报错也不跳转元素被遮挡 / 处于禁用态启用有头模式观察用locator.scroll_into_view_if_needed()检查元素状态不同用例互相串数据没有使用新的Context每条用例强制browser.new_context()或使用pytest-playwright的fixture浏览器下载慢或失败网络源问题配置PLAYWRIGHT_DOWNLOAD_HOST镜像环境变量并发跑用例报端口冲突用例内部启动了同端口的本地服务改用Context隔离避免共享本地端口或指定动态端口页面弹窗遮挡点击浮层广告 / 提示条先显式关闭浮层再执行主流程操作写在最后从零开始上手Playwright说难也不难但确实有不少一眼看不到的黑盒细节。我自己用过Selenium也用过Cypress最终在项目里稳定落地的是Playwright这套组合Playwright pytest Allure。踩过不少坑之后我的体会是自动化测试的真正门槛不在于会不会写脚本而在于能不能写出“稳定、可读、能定位问题”的用例。Playwright在稳定性这个问题上替我们挡了很多子弹剩下的就靠每次报错时多问一句“为什么”慢慢把经验攒起来。最后再分享一个小技巧跑用例时习惯性开一下trace和截图哪怕只跑通一遍也保留日志这个习惯会在交付测试用例给别人的时候省下大量解释成本。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑