Playwright 1.59 新特性:3 个 API 帮你告别 F12 手动找定位

Playwright 1.59 三个定位器新 API,把「F12 翻 DOM→手动改 selector」的工作流变成「指哪儿点哪儿→自动规范化→AI 生成 PO 骨架」。

学完你会获得:

① 三个 API(pickLocator / normalize / screencast)的完整代码示例,saucedemo 实战可跑

② 批量清洗现有项目定位器的工具脚本

③ 结合 AI 自动生成 Page Object 的 Prompt 模板

帮你少走弯路哦少踩坑。
* *

环境配置:安装与升级(Playwright v1.59)

新用户(从零开始):

Python 版pip install playwrightplaywright install# Node.js 版npm init playwright@latest

老用户升级:

Python 版pip install –upgrade playwrightplaywright install# Node.js 版npm install @playwright/test@latestnpx playwright install

Python 和 Node.js 都支持吗?

✅pickLocator()— Python + Node.js 均支持

✅locator.normalize()— Python + Node.js 均支持

✅page.screencast— Python + Node.js 均支持
* *

一、问题:1000+ 用例,定位器怎么写最快?

playwright 发布了最新的1.59版本,更新了不少内容,加强了AI Agent + 自动化测试。星主能不能介绍下具体的落地案例?
我现在还是F12一个一个的手动去写定位,有没有快速高效的案例,提升写用例的效率。现在已经维护了1000+的用例了。一个一个去找定位太慢了,虽然元素都加了testid了。

..生成整个 PO 模式的脚本,只需要人工调试修改定位表达式。想实现这种效果
「太慢了。能不能把页面地址丢给 AI,让它直接生成整个 PO 脚本?」

这个问题,Playwright 1.59 给了三个直接对口的答案。

但在讲 API 之前,先把定位策略优先级重申一遍——这是地基:

data-test > role > text > test_id > CSS > XPath
1.data-test:专门给测试预留,最稳
2.role:语义化定位,可访问性友好
3.text:文本定位,够直观
4.test_id:Playwright 内置测试属性
5.CSS:通用兜底
6.XPath:万不得已

下面三个 API,本质上是帮你在执行层更快地落地这套优先级框架。
* *

二、3 个 API 更新

2.1 page.pickLocator() —— 指哪儿点哪儿

这是 1.59 对测试人员最友好的功能。

以前怎么找定位器?(以 saucedemo.com 登录页为例)
1. 打开 https://www.saucedemo.com
2. F12 → 审查元素
3. 在密密麻麻的 DOM 里找到用户名输入框
4. 看到一个<input id="user-name" …>
5. 写#user-name,心里默念「这 id 应该不会变吧…」

现在呢?一行代码:

locator = await page.pick_locator()
运行后浏览器进入选取模式——鼠标悬停到哪个元素,哪个高亮,旁边实时显示定位器表达式。点一下就选中,locator 对象直接返回。

实战:pickLocator 选取 saucedemo 登录页元素

import asynciofrom playwright.asyncapi import asyncplaywrightasync def main():    async with asyncplaywright() as p:        browser = await p.chromium.launch(headless=False)        page = await browser.newpage()        await page.goto('https://www.saucedemo.com/', waituntil='networkidle')        print('n>>> 请在浏览器中点击「用户名输入框」')        usernameloc = await page.picklocator()        usernameloc = await usernameloc.normalize()        print(f'✅ 用户名输入框 → {usernameloc}')        print('n>>> 请点击「密码输入框」')        passwordloc = await page.picklocator()        passwordloc = await passwordloc.normalize()        print(f'✅ 密码输入框 → {passwordloc}')        print('n>>> 请点击「登录按钮」')        loginbtn = await page.picklocator()        loginbtn = await loginbtn.normalize()        print(f'✅ 登录按钮 → {loginbtn}')        await browser.close()asyncio.run(main())
运行这个脚本,你会在浏览器里点三个元素,终端立刻打印出三个已经规范化的定位器。

Playwright 1.59 新特性:3 个 API 帮你告别 F12 手动找定位

2.2 locator.normalize() —— 把烂定位器洗成最佳实践

上一个例子已经顺带演示了 normalize。这里单独展开讲讲它到底做了什么。

saucedemo 举例:商品页的按钮

saucedemo 的商品列表页,每个商品都有「ADD TO CART」按钮,HTML 长这样:

<button class="btn btnprimary btnsmall btn_inventory"        data-test="add-to-cart-sauce-labs-backpack">  Add to cart</button>
如果你手头有一段历史代码,用 CSS class 定位了这个按钮:

addtocartbtn = page.locator('.btninventory')
问题在于.btn_inventory这个 class 在页面里有 6 个(6 个商品各一个),会匹配到第一个,不稳定。

用 normalize 一键升级:

raw = page.locator('.btn_inventory')best = await raw.normalize()print(best)  # getByTestId('add-to-cart-sauce-labs-backpack')
normalize()按优先级检查:
1. 有没有data-test属性?→ 有,直接用getByTestId()
2. 有没有role?→ 有,用getByRole()
3. 有没有aria-label/placeholder?→ 有,用对应方法
4. 以上都没有 → 保留原选择器但尝试简化

对于前面读者提到的那 1000+ 条用例,可以写个脚本全量扫描一遍 PO 类文件,找出所有可以用 normalize 升级的定位器,批量建议替换。

批量扫描脚本(核心逻辑):

import refrom pathlib import PathNORMALIZERULES = [    (r'[data-tests*=s*["']([^"']+)["']]', r'getByTestId("1")'),    (r'[placeholders*=s*["']([^"']+)["']]', r'getByPlaceholder("1")'),]def scanpofiles(pagesdir='pages'):    for pyfile in Path(pagesdir).glob('*.py'):        if pyfile.name.startswith(''):            continue        with open(pyfile) as f:            lines = f.readlines()        for i, line in enumerate(lines, 1):            m = re.match(r'^s*(w+)s*=s*["']([^"']+)["']', line)            if not m:                continue            varname, locator = m.group(1), m.group(2)            if locator.startswith('getBy'):                continue            for pattern, repl in NORMALIZERULES:                if re.search(pattern, locator):                    print(f'{pyfile}:{i} | {varname} = "{locator}"')                    print(f'  → 建议改为: {re.sub(pattern, repl, locator)}')                    break
输出类似:

pages/inventorypage.py:18 | ADDTOCARTBUTTON = ".btninventory"  → 建议改为: getByTestId("add-to-cart-sauce-labs-backpack")pages/inventorypage.py:20 | CARTLINK = ".shoppingcart_link"  → 建议改为: getByTestId("shopping-cart-link")
一键看清哪些定位器需要升级。

2.3 page.screencast —— 测试跑完自动生成带标注的视频

排查失败用例最痛苦的是什么?不知道脚本点了哪里。

screencast 是 1.59 新增的录屏 API,比recordVideo更灵活,而且能在视频里标注每一步操作。

实战:录制 saucedemo 登录 + 加购完整流程

import asynciofrom playwright.asyncapi import asyncplaywrightasync def main():    async with asyncplaywright() as p:        browser = await p.chromium.launch(headless=False)        page = await browser.newpage()        # ===== 开始录屏 + 操作标注 =====        await page.screencast.start(path='saucedemologin.webm')        await page.screencast.showactions(position='top-right')        # 步骤 1:打开登录页        await page.screencast.showchapter('打开登录页')        await page.goto('https://www.saucedemo.com/', waituntil='networkidle')        # 步骤 2:输入用户名和密码        await page.screencast.showchapter('输入用户名')        await page.fill('#user-name', 'standarduser')        await page.fill('#password', 'secretsauce')        # 步骤 3:点击登录        await page.screencast.showchapter('点击登录')        await page.click('#login-button')        # 步骤 4:验证商品列表        await page.screencast.showchapter('验证登录成功')        await page.screencast.showoverlay('等待商品列表加载…')        await page.waitforselector('.inventorylist', timeout=5000)        # 步骤 5:添加商品到购物车        await page.screencast.showchapter('添加第一个商品')        await page.click('.btninventory')        cartbadge = page.locator('.shoppingcartbadge')        if await cartbadge.isvisible():            count = await cartbadge.innertext()            await page.screencast.show_overlay(f'购物车数量: {count}')        # ===== 停止录屏 =====        await page.screencast.stop()        print('✅ 视频已保存')        await browser.close()asyncio.run(main())
跑完这段脚本,你会得到一个.webm视频文件。打开播放:
• 右上角实时显示每一步的操作名(fill、click、wait)
• 被点击的元素会高亮闪烁
• 每一段有章节标记
• 自定义浮层(「等待商品列表加载…」「购物车数量: 1」)清晰可见

这个功能对于给 leader 演示或者排查 CI 上的偶发失败特别有用——不用再看截图猜谜了。
* *

三、AI 辅助生成 Page Object

上面三步走完,你已经能做到:
•定位器获取:pickLocator 指哪儿点哪儿
•定位器优化:normalize 自动洗成最佳实践
•调试回执:screencast 生成带标注的视频

但前面读者的最终目标更远——整个 PO 类的代码都由 AI 生成,人工只校对定位器和业务逻辑。

Step 1:用 Playwright 打开目标页面,抓取 DOM 结构快照

body = page.locator('body')snapshot = await body.aria_snapshot()print(snapshot)
Step 2:把「页面 URL + ARIA 快照 + 已知定位器」组成 Prompt,发给 LLM

你是一个 Playwright 自动化测试专家。## 页面信息- URL: https://www.saucedemo.com/inventory.html- 类名: InventoryPage## 已知定位器- ADDTOCARTBUTTON: getByTestId("add-to-cart-sauce-labs-backpack")- CARTBADGE: getByTestId("shopping-cart-badge")- CART_LINK: getByTestId("shopping-cart-link")## 页面 ARIA 结构[ariaSnapshot 输出…]## 要求生成完整的 InventoryPage 类,继承 BasePage,包含:- load() 方法加载页面- 根据页面元素推断可用的业务方法- 定位器使用已知定位器
Step 3:LLM 输出完整 PO 类,人工校对定位器 → 保存到项目 → 跑测试验证 → 通过后不再重复生成。

关键心法:AI 的正确用法不是让它每次跑测试时实时决策(那是 MCP 的坑),而是让它帮你生成一次固定的 PO 代码。代码一旦固化并通过测试,后续全是直接执行,没有幻觉,没有 token 消耗。
* *

四、踩坑 / Tips

| 坑 | 说明 | 解决 |
| — | — | — |
| pickLocator 必须 headless=False | 选取模式需要浏览器可交互,headless 下调用会报错 | 本地调试用 headless=False,CI 里别用 |
| normalize 不改写文件 | 它只返回新的定位器对象,不会帮你自动替换代码 | 搭配扫描脚本做批量替换建议 |
| screencast 输出 .webm | 企业微信/钉钉不一定能直接播 | 用 ffmpeg 转一下:ffmpeg -i input.webm output.mp4 |
| ariasnapshot 可能超时 | 页面 DOM 特别大时,快照生成慢 | 先waitforloadstate('domcontentloaded')再取 |
| pickLocator 选错元素 | 动态页面悬停时元素可能变 | 选之前先waitforload_state('networkidle') |
* *

五、总结

| 你的痛点 | 1.59 解法 | 一句话效果 |
| — | — | — |
| F12 手动找定位 | pickLocator() | 指哪儿点哪儿,不再翻 DOM |
| 脆弱的 CSS 选择器 | normalize() | 一键洗成 testid / role 最佳实践 |
| 排查失败靠猜 | screencast | 带标注的操作回执视频 |
| 手写 PO 类 | AI + ARIA 快照 | Prompt 模板直接生成,人工校对即可 |

一句话记住:1.59 把定位器工作流从「手动 F12 → 复制 selector → 手动改 testid」变成了「指哪儿点哪儿 → 自动规范化 → AI 生成 PO 骨架」。

省下的时间,够你多写 20 条用例。
* *

作业
1.必做:用 pickLocator 重新选取 saucedemo 商品列表页的 6 个「ADD TO CART」按钮定位器,对比 F12 方式的耗时
2.必做:跑一遍 normalize 扫描脚本,检查你现有项目的定位器有多少可以升级
3.选做:用 screencast 录制一段完整的登录→加购→结账流程,发给同事,看看他们能不能只看视频就理解测试步骤

前沿技术新闻资讯智能硬件

讯飞办公本用一键式龙虾部署,终结“只记不查”的资产浪费

2026-7-4 23:31:14

企业落地数字员工新闻资讯

AI智能体需要的是反馈循环,而不是完美的提示词

2026-7-4 23:45:15

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
购物车
优惠劵
搜索