news 2026/11/3 14:18:48

Playwright零基础入门:环境安装、首个脚本与元素定位避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Playwright零基础入门:环境安装、首个脚本与元素定位避坑指南

简介:《playwright自动化测试》是一份面向测试工程师与自学者编写、覆盖从入门到实践的Playwright文档,围绕微软Playwright的跨浏览器特性展开,帮助读者解决Chromium、Firefox、WebKit多浏览器环境下端到端测试的实施问题。文件包内共有1个docx文件,约17.16MB,按章节组织为Playwright概述、Python环境搭建、脚本实战与常用方法实践四部分;其中环境部分详细讲解PyCharm在Windows、Mac、Linux上的安装方法,以及更新pip、安装pytest-playwright与内置浏览器的完整流程。脚本部分以百度首页为样例,演示输入、点击、Web断言、命令行参数、录制用例与base_url的用法,并延伸至Click、hover、下拉框、页面导航等元素操作,同时涉及调试技巧、trace日志、并行执行与持续集成等实践要点。目前已有389人学习,适合零基础测试人员按目录逐步跟练,也可作为团队建立自动化测试规范的参考。

1. 先说人话:Playwright 到底是个什么东西

你有没有过这种经历:网页上有个表单,你每天要手动点几十遍,改一个字段、点一次提交、看一眼结果,点到最后手指发麻,还容易看漏。Playwright 就是替你干这件事的工具,它能像人一样打开浏览器、点按钮、往输入框里打字,再把结果拿回来告诉你对不对。

说得再直白点,它是一个浏览器自动化框架,支持 Chromium、Firefox、WebKit 三种浏览器内核,可以用 Python 写脚本去控制它们,也能用 JavaScript、Java 等语言。写自动化测试的人用它,做重复性网页操作的人也在用它。零基础完全可以上手,前提是你别一上来就啃原理,先把一个能看见结果的例子跑通。

2. 为什么零基础也该学:从每天点一百次到一个脚本跑完

先回答一个很多人心里没说出口的问题:我又不是专职测试,学这个干什么。答案很朴素——凡是「有规律、要重复、还得点很多次」的网页操作,都值得交给脚本。注册流程要验证三遍、改完一个配置要把五个页面点一遍、每次发版前要把主要功能走一遍,这些活在手工做的时候,出错率跟耐心成反比。

2.1 手工点页面这件事,到底卡在哪里

手工操作最麻烦的地方不是累,而是「不一致」。今天你心情好,点得仔细,能发现问题;明天赶时间,点得快,问题就滑过去了。第一个人点的时候先填了手机号再填验证码,第二个人反过来,结果可能完全不同。人在重复劳动里会自然走捷径,而走捷径的那部分,恰恰是最容易出问题的地方。

第二个麻烦是「覆盖不全」。一套后台系统,开发说支持三种浏览器,你手上有几台设备?大部分人只在自己常用的那个浏览器上点一遍,剩下两个靠运气。等到用户反馈某个按钮在另一个内核下点不动,你才知道漏了。

第三个麻烦是「没法重来」。手工测试做完就做完了,没有记录,没有截图,出了问题只能凭记忆回想当时点了什么。同事问你「昨天那个流程怎么走的」,你只能说「就那样走的啊」。

脚本能同时治好这三个毛病:它每次执行完全一样,不会因为今天心情好就多点两下;它可以在三种浏览器内核上轮流跑;它可以自动截图、自动记录每一步。

2.2 Playwright 跟别的方案比,新手能感知到的差别

市面上做浏览器自动化的工具不止一个,老牌的、新出的都有。对新手上手体验影响最大的,其实不是功能清单有多长,而是两件很具体的事:等元素和写定位。

「等元素」是自动化里最反直觉的一件事。页面还没加载完,脚本就去点按钮,必然报错;页面加载完了,但按钮是灰的,点了没反应。以前的做法是在每步前面加一句「睡三秒」,等页面自己缓过来。这种写法在本地跑得好好的,换台机器就全崩,因为那台机器可能更慢。这套东西被戏称为自动化的玄学部分,很多人第一次翻车就翻在这。

Playwright 把这件事做进了内核:它在执行点击、输入这类操作之前,会自己判断元素是不是已经出现在页面上、是不是可见、是不是可点,条件不满足就继续等,等到超时为止。你写脚本的时候不用再到处撒「睡三秒」。

提示:自动等待不是万能的。它只等「元素能不能操作」,不管「业务逻辑有没有跑完」。比如点了提交之后要等服务端返回,这种等待还是得你自己写断言去等结果。

另一件事是定位写法。Playwright 提供了一套按「人怎么看页面」来找元素的接口,比如「页面上写着登录的那个按钮」「占位符是请输入用户名的那一栏」。这种写法比一长串 div 套 div 的路径好读得多,页面改版的时候也不容易一夜之间全部失效。

还有几个特性属于「用上了就回不去」的:一是无头模式,浏览器不开窗口在后台跑,速度快、占资源少,适合放在服务器上定时执行;二是浏览器上下文,同一个浏览器实例里可以开多个互相隔离的环境,相当于同时模拟好几个用户登录,互不干扰;三是录制功能,你手动点一遍,它把脚本给你生成出来,不会写的时候可以直接「抄作业」。

2.3 装环境前先对一下清单:Python 和编辑器

装东西之前先确认两件事,能省掉后面一半的报错。

第一件是 Python 版本。Playwright 对 Python 的要求是 3.8 或更高。在命令行里敲python --version(Mac 和 Linux 上可能是python3 --version)就能看到。如果版本低于 3.8,先去装一个新的,别硬扛,低版本会遇到一堆依赖装不上的问题。

第二件是操作系统。Windows 10 及以上、Windows Server 2016 及以上都可以;macOS 建议 13 及以上;Linux 这边 Debian 11/12、Ubuntu 20.04/22.04/24.04 在 x86-64 和 arm64 架构上都支持。版本太老的系统不是完全不能跑,但浏览器内核可能起不来,新手排查这种问题非常痛苦,建议直接用受支持的版本。

编辑器用 PyCharm 社区版就够了。社区版功能比专业版少一些,但对写自动化脚本、调试、看报错这些事完全够用。安装过程不复杂:Windows 用户去官网下载.exe,双击一路下一步;Mac 用户下载对应芯片的安装包拖进应用目录;Linux 用户下载压缩包解压后进到bin目录执行启动脚本。这一步不用纠结,装完能新建一个项目、能打开终端就行。

注意:Windows 有两种处理器架构,AMD64 和 ARM64。下载前可以按Win + R输入cmd打开命令行,敲echo %PROCESSOR_ARCHITECTURE%看一眼,绝大多数人是 AMD64,选普通的.exe即可。

2.4 三条命令装完 Playwright 和它的浏览器

环境齐了就开始装。第一步先把 pip 升到最新,这一步很多人跳过,然后在安装环节遇到各种奇怪的依赖冲突。

# Windows python -m pip install --upgrade pip # macOS / Linux python3 -m pip install --upgrade pip

第二步装测试插件。这里的名字是pytest-playwright,它会把 Playwright 本体和 pytest 一起带进来,省得你分开装两遍。

pip install pytest-playwright

第三步,也是最容易被忘掉的一步:下载浏览器内核。

# 装全部三个内核:Chromium、Firefox、WebKit playwright install # 只装一个,省时间和磁盘 playwright install chromium

这里解释一下三行命令分别在干什么。第一行升级包管理工具本身,保证它能正确解析依赖;第二行装的是「Playwright + pytest 的胶水层」,装完之后你既能写普通脚本,也能写 pytest 风格的测试用例;第三行才是真正把浏览器下载到本地。

为什么单独有第三步?因为 Playwright 用的不是你自己电脑上装的那个浏览器,它下载的是一份专用的、版本固定的内核。这样做的好处是测试环境可控,不会因为你顺手升级了浏览器就突然跑不了;代价就是第一次要下载几百兆的东西,网速慢的时候会等一会儿。

装完之后验证一下,敲playwright --version,能打印出版本号就说明命令能用了。再跑一条最小命令确认浏览器能起得来:

# check.py from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch() # 默认无头模式,不弹窗口 page = browser.new_page() page.goto("https://example.com") print(page.title()) # 能打印出标题就说明通了 browser.close()

这段代码里,sync_playwright()是整个流程的入口,用with包起来是为了结束时自动清理资源;launch()负责启动浏览器,不传参数时默认无头;new_page()开一个空白标签页;goto()访问地址;title()取页面标题。如果这四行能跑通并打印出东西,说明环境和浏览器都就位了,接下来才谈得上写业务脚本。

3. 第一个能跑的例子:10 行代码打开浏览器并拿到结果

环境装完,接下来是让新手最有成就感的一步:亲手跑通第一个脚本。这里我特意把例子拆成四个小台阶,每一个都只比上一步多一点点,跑通了再加下一层。别一上来就抄一段几十行的完整用例,看不懂的代码跑通了也没意义。

3.1 第一条脚本:打开页面、打印标题、截个图

新建一个文件,比如叫first.py,把下面这段抄进去。

# first.py from playwright.sync_api import sync_playwright with sync_playwright() as p: # headless=False 表示弹出真实浏览器窗口,方便新手观察 browser = p.chromium.launch(headless=False) page = browser.new_page() # 新开一个标签页 page.goto("https://example.com") # 访问目标地址 print(page.title()) # 打印页面标题 page.screenshot(path="first.png") # 截图保存到当前目录 browser.close() # 关闭浏览器

逐行解释一下。headless=False是给新手用的,你会看到一个浏览器窗口自己弹出来、自己打开网址,这个画面比任何文档都有说服力;等你写熟了再改回默认的无头模式。goto()默认会等页面加载到一定阶段才返回,不需要你额外加等待。screenshot(path=...)里的path是保存路径,写相对路径就存在脚本所在的目录,写绝对路径也可以,但换机器跑就会失效,不建议。

跑之前确认一下当前目录,别让截图生成到你看不见的地方。在 PyCharm 里右键运行,或者在终端里敲python first.py。窗口一闪而过是正常的,脚本执行完就关掉了,去目录里找那张图确认一下。

3.2 往输入框里打字,再点按钮

只会打开页面还不算自动化,能操作才算。为了不依赖外网、不受目标站点改版影响,这里我用一段本地 HTML 造一个带输入框和按钮的小页面,把它塞进浏览器里。

# input_demo.py from playwright.sync_api import sync_playwright html = """ <html><body> <input id="kw" placeholder="请输入关键词"> <button id="go">搜索</button> <p id="out"></p> <script> document.getElementById('go').onclick = () => { document.getElementById('out').textContent = '你搜索的是:' + document.getElementById('kw').value; }; </script> </body></html> """ with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.set_content(html) # 把上面这段 HTML 加载进来 page.locator("#kw").fill("playwright") # 往输入框填内容 page.locator("#go").click() # 点按钮 print(page.locator("#out").inner_text()) # 打印结果文字 browser.close()

这里有三个关键方法要记住。set_content()是把一段 HTML 字符串直接当成页面内容加载,适合做不依赖外部站点的练习;fill()是往输入框里塞文本,它跟逐字敲键盘不一样,是一次性赋值,速度快且稳定,适合绝大多数场景;click()就是点击。

locator("#kw")里的#kw是 CSS 选择器写法,#表示 id。这段代码执行完,控制台应该打印出你搜索的是:playwright。如果你看到的不是这个结果,先检查fill那行是不是写在了set_content前面,顺序错了页面还没加载,元素自然找不到。

3.3 加断言:怎么让脚本自己判断对错

打印结果只能让人眼看,人眼看就有看漏的时候。真正让脚本有价值的是断言——脚本自己判断结果对不对,不对就报错。

# assert_demo.py from playwright.sync_api import sync_playwright, expect with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.set_content(""" <input id="kw" placeholder="请输入关键词"> <button id="go">搜索</button> <p id="out"></p> <script> document.getElementById('go').onclick = () => { document.getElementById('out').textContent = '你搜索的是:' + document.getElementById('kw').value; }; </script> """) page.locator("#kw").fill("playwright") page.locator("#go").click() # 断言:结果区域的文字应当等于预期值 expect(page.locator("#out")).to_have_text("你搜索的是:playwright") print("断言通过") browser.close()

expect()是 Playwright 的断言入口,to_have_text()表示「文字应当等于某个值」。它跟普通断言最大的区别是自带重试:如果此刻文字还没渲染出来,它会在超时时间里反复检查,而不是立刻判失败。这个特性对前端渲染慢的页面特别有用。

常用的断言还有几个:to_be_visible()判断元素是否可见,to_have_value()判断输入框里的值,to_have_count()判断列表里有几条。新手先把to_have_text和to_be_visible用熟,能覆盖大部分场景。

提示:断言失败时不要急着改代码,先把报错信息完整读一遍。Playwright 的失败信息里会写上「期望什么、实际是什么、等了多少毫秒」,这三条信息基本能定位到八成问题。

3.4 不会写就让它替你写:录制功能怎么用

新手最常卡住的地方是「不知道某个按钮该怎么定位」。Playwright 自带一个录制工具,你手动点一遍,它把对应的代码生成出来,你复制回去改改就能用。

# 打开一个浏览器窗口和代码生成器 playwright codegen https://example.com

执行之后会弹出两个窗口,一个是正常浏览器,一个是代码面板。你在浏览器里点一下、输入点内容,代码面板里就会实时出现对应的 Python 代码。录完之后复制下来,删掉多余的步骤,把定位改得更稳一点,就能用了。

录制出来的代码不能直接当最终版本用,原因是它记录的定位往往偏向「第几个 div 下面第几个按钮」这种脆弱写法,页面一改版就失效。它的正确用法是帮你快速看到「这个操作大概长什么样」,然后你照着它的思路换成更稳的定位方式,比如按文本、按角色去找。

顺带说一个跟命令行有关的小配置。跑 pytest 的时候可以加参数临时切换浏览器和运行模式,不用改代码:

# --headed 弹出窗口,--browser 指定内核,--slowmo 放慢操作便于观察 pytest --headed --browser chromium --slowmo 500 --base-url https://example.com

--base-url这个参数值得单独说一下。它把「站点地址」从代码里抽出来变成启动参数,代码里只写相对路径page.goto("/login"),换环境的时候改参数就行,不用满文件搜索替换网址。这是后面做多环境测试的基础,现在先知道有这个用法。

4. 元素定位:为什么你的脚本总在「找不到」上卡死

写脚本的时间,八成花在定位上;报错的原因,八成也是定位。这一章不讲全,只讲新手够用的那一部分,把最常用的几把工具交到你手上。定位的核心逻辑其实只有一句话:你怎么跟同事描述「点那个按钮」,就怎么跟脚本描述。同事听得懂的说法,脚本大概率也听得懂。

4.1 优先用「人话」定位:role、text、label、placeholder、title

Playwright 提供的这套接口,思路是模仿用户怎么看页面。用户看到的是「一个写着登录的按钮」「一个提示输入用户名的框」,那我们就按这个描述去找。

# locate_demo.py from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.set_content(""" <html><body> <label for="username">用户名</label> <input id="username" placeholder="请输入用户名"> <button title="提交登录">登录</button> <ul> <li class="item">苹果</li> <li class="item">香蕉</li> <li class="item">橘子</li> </ul> </body></html> """) # 1. 按 label 文字定位输入框 page.get_by_label("用户名").fill("tester") # 2. 按 placeholder 定位输入框 page.get_by_placeholder("请输入用户名").fill("tester2") # 3. 按角色 + 可访问名称定位按钮 page.get_by_role("button", name="登录").click() # 4. 按可见文本定位列表项 page.get_by_text("香蕉").click() browser.close()

解释一下这几个方法的适用场景。get_by_role("button", name="登录")里的name不是元素的 name 属性,而是「用户能读到的那个名字」,对按钮来说就是它上面写的字。get_by_label()靠的是表单标签和输入框的关联关系,是无障碍访问中最标准的写法,页面一般不会随便改。get_by_placeholder()靠占位符文字,好认,但如果页面文案是产品经理天天改的那种,就会脆。

get_by_text()适合点链接、点菜单、点列表里的某一项。还有一个get_by_title(),是靠元素的title属性定位,用来兜底一些上面几种都覆盖不到的场景。

为什么优先推荐这一套?因为它们的写法跟页面结构解耦。页面把按钮从左边挪到右边、从 div 换成 span,只要文字没变,定位就还成立。而按层级路径写的那种定位,改一个布局就全废。

4.2 CSS 和 XPath:什么时候才轮到它们

上面的方法覆盖不到的时候,才退回到 CSS 或者 XPath。这两种是通用的选择器语法,表达能力强,但可读性差,维护成本高。

# CSS 写法 page.locator("#username") # id 选择器 page.locator(".item") # class 选择器 page.locator("ul.item-list > li:nth-child(2)") # 层级 + 序号 page.locator("input[placeholder*='用户名']") # 属性包含匹配 # XPath 写法,Playwright 里以 // 开头会自动识别 page.locator("//button[text()='登录']") page.locator("xpath=//ul/li[2]")

给新手一条实用原则:能用文字定位就不用 CSS,能用简单 CSS 就不用带好几层结构的 CSS,能用 CSS 就别碰 XPath。XPath 写起来灵活,但一旦页面结构变了,它往往是最难排查的那种失败。

什么时候 CSS 确实更合适?列表、表格这类有重复结构的元素,按 class 批量拿再按序号取,比一个个按文本找省事。这个在第 4.3 节里会展开。

4.3 等不到、找不到、找到多个:filter、nth、first、last 的用法

真实页面里,「按文本找」经常撞车:页面上有三个「删除」按钮,分属三行数据。这时候直接写get_by_text("删除")会报错说匹配到了多个元素。解决办法是先圈定范围,再在范围里找。

# 先按内容过滤出目标行,再在行内点按钮 row = page.locator("tr").filter(has_text="张三") row.get_by_role("button", name="删除").click() # 按序号取:nth 从 0 开始 page.locator(".item").nth(0).click() # 第 1 个 page.locator(".item").first.click() # 第一个,等价于 nth(0) page.locator(".item").last.click() # 最后一个 # 只保留可见的元素,避免匹配到被隐藏的节点 page.locator(".item").filter(visible=True)

filter(has_text=...)的意思是「在这个范围里,包含某段文字的留下」。它比直接用 XPath 写一长串条件可读性好得多,也更贴近人找元素的思路:先找到张三那一行,再点那一行的删除。

filter(visible=True)是个很实用的开关。很多页面上会有隐藏的、重复的元素,比如移动端和桌面端各渲染一份,靠显示状态区分。不加这个过滤,脚本可能匹配到那个看不见的,然后在点击时超时。

另外 Playwright 还提供了逻辑组合的能力,比如locator("a").and_(page.get_by_text("详情"))表示「既是链接、文字又是详情」,or_()表示满足其一即可。这些用得不算多,知道有这么回事就行,真遇到了再查。

4.4 iframe 里的元素怎么找:定位最容易翻车的地方

现代后台系统特别喜欢嵌 iframe,尤其是登录、支付、富文本编辑器这些模块。iframe 里的元素,在外层页面是直接找不到的,这是新手最高频的翻车点之一。

# 先进入 iframe,再在里面定位 frame = page.frame_locator("iframe#pay") frame.get_by_role("button", name="确认支付").click() frame.get_by_placeholder("请输入密码").fill("123456")

frame_locator()的用法跟页面级的locator()几乎一样,只是之后所有的定位都要基于这个frame对象来写,不能再用page。如果 iframe 是嵌套的,就一层一层拿到里层。

怎么判断元素到底在不在 iframe 里?在浏览器开发者工具里选中那个元素,看它的祖先节点里有没有iframe标签。有的话就是;还有一个更快的判断方法:脚本报超时,但你在页面上明明看得见这个元素,八成就是在 iframe 里。

注意:iframe 加载是异步的,有时候外层页面已经好了,iframe 里还是空的。frame_locator()本身带等待,但如果 iframe 的地址是后设置的,需要先等 iframe 元素出现,再进里面操作。

5. 新手避坑:五个我真实翻车过的场景

这一章列的都是我自己踩过的坑,每一条都按「现象 → 原因 → 解决」写。看的时候不用记,等真遇到了再回来翻。新手期最浪费时间的不是不会写,而是报错信息看不懂,然后开始瞎改。

5.1 坑一:装完库却起不来浏览器,报可执行文件不存在

现象:代码写得没问题,一运行就报类似Executable doesn't exist at ...的错误,提示某个路径下找不到浏览器。

原因:只装了 Python 库,没下载浏览器内核。这两步是分开的,pip install pytest-playwright只装代码,不带几百兆的内核文件。

解决:执行playwright install,要快一点就指定单个内核playwright install chromium。装完如果还报同样的错,检查一下是不是在虚拟环境里运行的,虚拟环境切换后可能需要重装一次。

5.2 坑二:元素明明在页面上,脚本就是报超时

现象:你盯着浏览器窗口,那个按钮就在那儿,脚本等了几十秒然后失败,报元素不可见或没找到。

原因:通常有三种。一是元素在 iframe 里,外层页面找不到;二是元素被弹窗、遮罩、悬浮工具栏挡住了,看得见但点不着;三是元素确实存在但被 CSS 设成不可见,比如高度为 0 或者被移出可视区。

解决:先确认是不是 iframe,是就用frame_locator();如果是被遮挡,先关掉弹窗或者等遮罩消失再点;如果只是渲染延迟,用expect(...).to_be_visible()主动等它出现,而不是加固定时长的睡眠。

5.3 坑三:本地跑得好好的,换台机器或者换个模式就挂

现象:在自己电脑上弹着窗口跑,一切正常;改成无头模式,或者到同事电脑上跑,脚本开始报元素点不到。

原因:无头模式和带窗口模式的默认窗口尺寸不一样,有些页面在窄屏下会把按钮收进折叠菜单里,元素虽然存在但不在可视区域;另外不同机器的系统缩放、字体渲染也有差异。

解决:显式设置窗口大小,别依赖默认值。

browser = p.chromium.launch(headless=True) page = browser.new_page(viewport={"width": 1440, "height": 900})

设完之后本地和服务器上尺寸一致,这类问题基本消失。这一条属于不看就永远想不到、看了就再也不会犯的类型。

5.4 坑四:一个用例能跑,一串用例一起跑就互相干扰

现象:单独跑某个测试文件,通过;把整个目录一起跑,中间几个开始失败,报数据和预期对不上。

原因:用例之间共享了状态。上一个用例登录了、建了一条数据,下一个用例进去看到的就不是初始状态;或者上一个用例改了密码,后面全部登录失败。

解决:每个用例开始前把环境恢复成已知状态。常见做法是用 fixture 在用例前准备数据、用例后清理数据,登录态则单独保存和复用,不要每个用例都重新走一遍登录流程。这属于工程习惯问题,一开始就养成,后面能省很多事。

5.5 坑五:把绝对路径和硬编码时间写进脚本

现象:脚本在自己机器上跑了三个月,突然某天开始失败;或者发给同事,别人一运行就报文件找不到。

原因:写死了本机的绝对路径(比如截图存到某个盘符下的某个目录),或者写死了「等 5 秒」「用当前时间戳当名字」这类和机器环境绑定的东西。

解决:路径一律用相对路径或者由代码动态生成;时间相关的数据处理,把「当前时间」抽成一个变量,方便替换;截图和下载文件的目录用配置项传进去。这类问题单个看不致命,攒多了会让整套脚本变得没法维护。

提示:报错信息里带「timeout」的,九成是等待问题;带「strict mode violation」的,是定位匹配到了多个元素;带「not visible」的,是被遮挡或者不在视口内。先按关键词分类,再针对性排查,比无头苍蝇式地改代码快得多。

6. 下一步学什么:从会跑脚本到能维护一套用例

跑通第一个例子之后,最容易走的弯路是马上开始写一大堆脚本,写完发现全散在一个文件里,改一个定位要改十几个地方。真正该补的是组织方式,而不是更多的 API。

下面这条路线是我带新人时最常用的顺序,供你参考:

阶段要掌握的东西大概投入
第一周跑通例子,熟悉 fill、click、goto、expect每天半小时
第二周把脚本改成 pytest 用例,用 fixture 准备数据和清理每天一小时
第三周学页面对象封装,把定位和操作从用例里抽出来每天一小时
第四周学登录态复用、失败重试、报告输出按需

第三周那个「页面对象封装」听起来唬人,其实就是把「登录页有哪些元素、能做哪些操作」单独写成一个类,用例里只写「打开登录页,用某账号登录」这种业务语言。这样做的好处是页面改版时只改一个文件,用例不用动。

有一个技巧现在就能用上:登录别每次都走一遍界面。Playwright 支持把登录后的状态存下来,下次直接加载。

# 第一次:正常登录,把登录态存到文件 context = browser.new_context() page = context.new_page() page.goto("https://example.com/login") page.get_by_label("用户名").fill("tester") page.get_by_label("密码").fill("123456") page.get_by_role("button", name="登录").click() context.storage_state(path="auth.json") # 保存鉴权信息 # 之后每次:直接加载,跳过登录步骤 context = browser.new_context(storage_state="auth.json")

storage_state保存的是 cookie 和本地存储这类身份信息,new_context(storage_state=...)把它加载回来。注意这个文件等同于账号密码,不要提交到代码仓库里。我第一次用这个功能的时候,图省事把文件一起传上去了,后来被同事提醒才改,从那以后我每次新建项目,第一件事就是把它加进忽略列表。

学习节奏上,别追求把 API 全看一遍。Playwright 的方法很多,但 80% 的脚本只用到十来个。遇到不会的,先去查官方文档的对应页面,比看二手教程准确。真卡住了,把报错信息完整贴出来再搜,搜到的答案相关性会高很多。

另外提醒一句心态上的事:脚本失败是常态,不是你的问题。页面在变、网络在变、数据在变,任何一套自动化用例都需要持续维护。把它当成一个会生长的东西,而不是一次写完就完事的作业,你会轻松很多。从那以后我每次新写一个脚本,都强制先跑一遍录制、再手写一遍定位,两相对照,能提前发现不少隐患。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/3 14:18:47

生物信息学与智能计算会议投稿与参会指南

1. 会议背景与核心价值解析 生物信息学与智能计算作为交叉学科的前沿领域&#xff0c;正在重塑生命科学研究的范式。BIC系列会议自2016年创办以来&#xff0c;已成功搭建起亚太地区该领域最具活力的学术交流平台。2026年第六届会议选址粤港澳大湾区核心城市东莞&#xff0c;由香…

作者头像 李华
网站建设 2026/11/3 14:17:35

AVPlayer音乐播放器开发核心技术与实践

1. AVPlayer音乐播放器开发全景解析 作为iOS/macOS平台的原生多媒体框架&#xff0c;AVFoundation中的AVPlayer组件一直是构建专业级音乐播放器的首选方案。我在过去五年中主导开发过三款音乐类应用&#xff0c;从简单的本地播放器到支持千万级曲库的流媒体应用&#xff0c;AVP…

作者头像 李华
网站建设 2026/11/3 14:17:34

军工系统大文件分块传输与WebUploader改造实践

1. 军工系统大文件传输的特殊需求解析在军工系统的局域网环境中&#xff0c;大文件传输面临着比普通企业网络更为严苛的技术要求。军工单位的网络架构通常采用物理隔离的内网部署&#xff0c;带宽资源有限且需要兼顾多个保密系统的并行运行。我们曾遇到过某型号装备测试数据的传…

作者头像 李华
网站建设 2026/11/3 14:17:22

Doris在零售推荐系统中的实时分析与优化实践

1. Doris在零售科技领域的核心价值解析 零售行业正面临数据爆炸式增长的挑战&#xff1a;每天产生数百万条交易记录、用户行为数据和商品信息。传统数据库在处理这种PB级实时分析时显得力不从心&#xff0c;而Apache Doris凭借其MPP架构和列式存储引擎&#xff0c;成为解决这一…

作者头像 李华
网站建设 2026/11/3 14:17:10

Word图片粘贴到网页编辑器的技术解决方案

1. 从Word粘贴图片到网页编辑器的技术挑战 作为一名长期与内容管理系统打交道的老兵&#xff0c;我见过太多编辑人员在从Word文档向网页编辑器粘贴内容时遭遇的图片丢失问题。这看似简单的操作背后&#xff0c;隐藏着一系列值得深究的技术细节。 当用户从Word复制内容到KindEd…

作者头像 李华
网站建设 2026/11/3 14:16:43

身份证正则表达式与校验位实战:从表单校验到数据清洗

身份证正则表达式这个东西&#xff0c;几乎每个写过表单校验的人都被它折腾过一次。我见过的写法五花八门&#xff0c;从最早的^\d{18}$&#xff0c;到后来动辄一百多个字符的超长正则都有&#xff0c;但真正上线之后能同时做到"不误杀正常用户、不放行脏数据、报错提示还…

作者头像 李华