《刚刚问世》系列初窥篇-Java+Playwright自动化测试-7-元素基础定位方式-下篇 (详细教程)
1.简介
上一篇主要是讲解我们日常工作中在使用Playwright进行元素定位的一些比较常用的基础定位方式的理论基础知识以及在什么情况下推荐使用。今天这一篇讲解和分享一下剩下部分的基础定位方式。
2.过滤器定位
例如以下 DOM 结构,我们要在其中单击第二个产品卡的购买按钮。我们有几个选项来过滤定位器以获得正确的定位器。

2.1按文本过滤
定位器可以使用 locator.filter()方法按文本进行过滤。它将搜索元素内某处的特定字符串,可能在后代元素中,不区分大小写。您还可以传递正则表达式。
1.使用文本
page.getByRole(AriaRole.LISTITEM)
.filter(new Locator.FilterOptions().setHasText("Product 2"))
.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Add to cart"))
.click();
2.使用正则表达式
page.getByRole(AriaRole.LISTITEM)
.filter(new Locator.FilterOptions()
.setHasText(Pattern.compile("Product 2")))
.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Add to cart"))
.click();
2.2按没有文本进行筛选
通过没有文本进行筛选:
// 5 in-stock items
assertThat(page.getByRole(AriaRole.LISTITEM)
.filter(new Locator.FilterOptions().setHasNotText("Out of stock")))
.hasCount(5);
2.3子项/后代过滤
定位器支持一个选项,即仅选择具有或没有与另一个定位器匹配的后代的元素的元素。因此,您可以按任何其他定位器进行过滤,例如 Locator.getByRole()、Locator.getByTestId()、Locator.getByText() 等。

page.getByRole(AriaRole.LISTITEM)
.filter(new Locator.FilterOptions()
.setHas(page.GetByRole(AriaRole.HEADING, new Page.GetByRoleOptions()
.setName("Product 2"))))
.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Add to cart"))
.click()
我们还可以断言产品卡,以确保只有一个:
assertThat(page
.getByRole(AriaRole.LISTITEM)
.filter(new Locator.FilterOptions()
.setHas(page.GetByRole(AriaRole.HEADING,
new Page.GetByRoleOptions().setName("Product 2"))))
.hasCount(1);
过滤定位器必须相对于原始定位器进行查询,并且从原始定位器匹配项开始进行查询,而不是从文档根开始进行查询。因此,以下操作将不起作用,因为过滤定位器从列表元素开始匹配,该列表元素位于原始定位器匹配的列表项之外:<ul><li>
// WRONG
assertThat(page
.getByRole(AriaRole.LISTITEM)
.filter(new Locator.FilterOptions()
.setHas(page.GetByRole(AriaRole.LIST)
.GetByRole(AriaRole.HEADING,
new Page.GetByRoleOptions().setName("Product 2"))))
.hasCount(1);
2.4按没有子项/后代过滤
我们也可以通过内部没有匹配的元素来过滤。
assertThat(page
.getByRole(AriaRole.LISTITEM)
.filter(new Locator.FilterOptions().setHasNot(page.getByText("Product 2")))
.hasCount(1);
敲黑板!!!!请注意,内部定位器是从外部定位符开始匹配的,而不是从文档根目录开始匹配的。
3.定位器操作员
3.1定位器内部匹配
您可以链接创建定位器的方法,例如 Page.getByText() 或 Locator.getByRole(),以将搜索范围缩小到页面的特定部分。
在此示例中,我们首先通过定位其角色listitem来创建一个名为 product 的定位器。然后,我们按文本进行过滤。我们可以再次使用产品定位器来获取按钮的角色并单击它,然后使用断言来确保只有一个文本为“产品 2”的产品。
Locator product = page
.getByRole(AriaRole.LISTITEM)
.filter(new Locator.FilterOptions().setHasText("Product 2")); product
.getByRole(AriaRole.BUTTON,
new Locator.GetByRoleOptions().setName("Add to cart"))
.click();
您还可以将两个定位器链接在一起,例如,在特定对话框中查找“保存”按钮:
Locator saveButton = page.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Save"));
// ...
Locator dialog = page.getByTestId("settings-dialog");
dialog.locator(saveButton).click();
3.2同时匹配两个定位器
方法 Locator.and()通过匹配其他定位器来缩小现有定位器的范围。例如,您可以将 Page.getByRole() 和 Page.getByTitle() 组合在一起,以按角色和标题进行匹配。
Locator button = page.getByRole(AriaRole.BUTTON).and(page.getByTitle("Subscribe"));
3.3匹配两个备选定位器之一
如果您想定位两个或多个元素中的一个,但不知道会是哪一个,请使用 Locator.or() 创建一个与所有备选项匹配的定位器。
例如,考虑这样一种情况:您想单击“新电子邮件”按钮,但有时会出现安全设置对话框。在这种情况下,您可以等待“新电子邮件”按钮或对话框,然后采取相应措施。
敲黑板!!!注意:
如果屏幕上同时出现“新建电子邮件”按钮和安全对话框,则“或”定位器将匹配它们,从而可能引发“严格模式违规”错误。在这种情况下,您可以使用 Locator.first() 仅匹配其中一个。
Locator newEmail = page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("New"));
Locator dialog = page.getByText("Confirm security settings");
assertThat(newEmail.or(dialog).first()).isVisible();
if (dialog.isVisible())
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Dismiss")).click();
newEmail.click();
3.4仅匹配可见元素
敲黑板!!!注意:
通常,找到一种更可靠的方法来唯一标识元素,而不是检查可见性。
考虑一个有两个按钮的页面,第一个不可见,第二个可见。
<button style='display: none'>Invisible</button>
<button>Visible</button>
这将找到两个按钮并抛出严格性违规错误:
page.locator("button").click();
这只会找到第二个按钮,因为它是可见的,然后单击它。
page.locator("button").locator("visible=true").click();
4.列表
4.1对列表中的项目进行计数
可以断言定位器以对列表中的项目进行计数。例如:以下DOM结构

使用count断言确保列表包含 3 个项目。
assertThat(page.getByRole(AriaRole.LISTITEM).hasCount(3);
4.2断言列表中所有文本
可以断言定位器以查找列表中的所有文本。例如:以下DOM结构

使用 assertThat(locator).hasText() 确保列表包含文本“apple”、“banana”和“orange”。
assertThat(page
.getByRole(AriaRole.LISTITEM))
.hasText(new String[] { "apple", "banana", "orange" });
4.3定位特定项目
有许多方法可以在列表中定位特定项目。
4.3.1通过文本定位
使用 Page.getByText()方法通过文本内容在列表中查找元素,然后单击它。例如:以下DOM结构

通过文本内容找到项目并单击它。
page.getByText("orange").click();
4.3.2通过文本过滤定位
使用 locator.filter() 在列表中查找特定项目。例如:以下DOM结构

按“listitem”的角色找到一个项目,然后按“orange”的文本进行筛选,然后单击它。
page.getByRole(AriaRole.LISTITEM)
.filter(new Locator.FilterOptions().setHasText("orange"))
.click();
4.3.3通过测试id定位
使用 Page.getByTestId()方法在列表中查找元素。如果您还没有测试 ID,则可能需要修改 html 并添加测试 ID。

通过测试 ID “orange”找到一个项目,然后单击它。
page.getByTestId("orange").click();
4.3.4通过第n项定位
如果您有一个相同元素的列表,并且区分它们的唯一方法是顺序,则可以使用 Locator.first()、Locator.last() 或 Locator.nth() 从列表中选择特定元素。
Locator banana = page.getByRole(AriaRole.LISTITEM).nth(1);
但是,请谨慎使用此方法。通常,页面可能会发生变化,定位器将指向与您预期的完全不同的元素。取而代之的是,尝试提出一个独特的定位器,该定位器将通过严格的标准。
4.4链接过滤器
当您有各种相似性的元素时,可以使用 locator.filter()方法选择正确的元素。您还可以链接多个筛选器以缩小选择范围。

要截取带有“Mary”和“Say goodbye”的行的屏幕截图,请执行以下操作:
Locator rowLocator = page.getByRole(AriaRole.LISTITEM); rowLocator
.filter(new Locator.FilterOptions().setHasText("Mary"))
.filter(new Locator.FilterOptions()
.setHas(page.getByRole(
AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Say goodbye"))))
.screenshot(new Page.ScreenshotOptions().setPath("screenshot.png"));
现在,您应该在项目的根目录中有一个“screenshot.png”文件。
4.5罕见例子
4.5.1对列表中每个元素执行某些操作
迭代元素
for (Locator row : page.getByRole(AriaRole.LISTITEM).all())
System.out.println(row.textContent());
使用常规 for 循环进行迭代:
Locator rows = page.getByRole(AriaRole.LISTITEM);
int count = rows.count();
for (int i = 0; i < count; ++i)
System.out.println(rows.nth(i).textContent());
4.5.2在页面中评估
locator.evaluate_all()中的代码在页面中运行,您可以在那里调用任何 DOM API。
Locator rows = page.getByRole(AriaRole.LISTITEM);
Object texts = rows.evaluateAll(
"list => list.map(element => element.textContent)");
5.小结
定位器是非常严格。这意味着,如果多个元素匹配,则对定位器执行暗示某些目标 DOM 元素的所有操作都将引发异常。例如,如果 DOM 中有多个按钮,则会引发以下调用:
如果有多个button,则引发错误
page.getByRole(AriaRole.BUTTON).click();
另一方面,Playwright 了解何时执行多元素操作,因此当定位器解析为多个元素时,以下调用工作正常。
适用于多个元素
page.getByRole(AriaRole.BUTTON).count();
您可以通过 locator.first、locator.last 和 locator.nth() 告诉 Playwright 在多个元素匹配时使用哪个元素来明确选择退出严格性检查。不建议使用这些方法,因为当您的页面更改时,Playwright 可能会单击您不想要的元素。相反,请按照上述最佳实践创建唯一标识目标元素的定位器。
5.1其他定位器
对于不太常用的定位器,请查看官网的其他定位器指南。由于时间关系,宏哥就不在这里对其进行展开介绍和讲解了。好了时间不早了,关于元素基础定位方式今天就分享到这里!!!仅供大家学习参考,感谢您耐心的阅读。
《刚刚问世》系列初窥篇-Java+Playwright自动化测试-7-元素基础定位方式-下篇 (详细教程)的更多相关文章
- 《手把手教你》系列技巧篇(四十七)-java+ selenium自动化测试-判断元素是否显示(详解教程)
1.简介 webdriver有三种判断元素状态的方法,分别是isEnabled,isSelected 和 isDisplayed,其中isSelected在前面的内容中已经简单的介绍了,isSelec ...
- 《手把手教你》系列技巧篇(四十八)-java+ selenium自动化测试-判断元素是否可操作(详解教程)
1.简介 webdriver有三种判断元素状态的方法,分别是isEnabled,isSelected 和 isDisplayed,其中isSelected在前面的内容中已经简单的介绍了,isSelec ...
- 《手把手教你》系列基础篇之(一)-java+ selenium自动化测试-环境搭建(上)(详细教程)
1.简介 jmeter系列的文章结束,本来想趁热打铁顺别将Jmeter和接口测试介绍一下,但是感觉Jmeter时间太长了怕大家吃腻了,还有一个原因就是许多小伙伴们或者童鞋们私信问宏哥什么时候可以有ja ...
- 《手把手教你》系列基础篇(五)-java+ selenium自动化测试- 创建首个自动化脚本(详细教程)
1.简介 前面几篇宏哥介绍了两种(java和maven)环境搭建和三大浏览器的启动方法,这篇文章宏哥将要介绍第一个自动化测试脚本.前边环境都搭建成功了,浏览器也驱动成功了,那么我们不着急学习其他内容, ...
- 《手把手教你》系列技巧篇(二十八)-java+ selenium自动化测试-处理模态对话框弹窗(详解教程)
1.简介 在前边的文章中窗口句柄切换宏哥介绍了switchTo方法,这篇继续介绍switchTo中关于处理alert弹窗的问题.很多时候,我们进入一个网站,就会弹窗一个alert框,有些我们直接关闭, ...
- 《手把手教你》系列技巧篇(三十二)-java+ selenium自动化测试-select 下拉框(详解教程)
1.简介 在实际自动化测试过程中,我们也避免不了会遇到下拉选择的测试,因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助. 2.select 下拉框 2.1Select ...
- 《手把手教你》系列基础篇(七十六)-java+ selenium自动化测试-框架设计基础-TestNG实现DDT - 下篇(详解教程)
1.简介 今天这一篇宏哥主要是结合实际工作中将遇到的测试场景和前边两篇学习的知识结合起来给大家讲解和分享一下,希望以后大家在以后遇到其他的测试场景也可以将自己的所学的知识应用到测试场景中. 2.测试场 ...
- 《手把手教你》系列基础篇(八十五)-java+ selenium自动化测试-框架设计基础-TestNG自定义日志-下篇(详解教程)
1.简介 TestNG为日志记录和报告提供的不同选项.现在,宏哥讲解分享如何开始使用它们.首先,我们将编写一个示例程序,在该程序中我们将使用 ITestListener方法进行日志记录. 2.Test ...
- 《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
1.简介 上一篇宏哥用PageFactory实现了POM,宏哥再介绍一下如果不用PageFactory如何实现POM. 2.项目实战 在这里宏哥以百度首页登录的例子,如果用POM实现,在测试脚本中实际 ...
- spring 5.x 系列第6篇 —— 整合 mybatis + druid 连接池 (代码配置方式)
源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 项目目录结构 1.创建maven工程,除了Spring基本依赖外,还需要导 ...
随机推荐
- Nuxt.js 应用中的 app:mounted 钩子详解
title: Nuxt.js 应用中的 app:mounted 钩子详解 date: 2024/10/5 updated: 2024/10/5 author: cmdragon excerpt: ap ...
- Windows 10 LTSC 2019(1809) WSL 安装 CentOS 7
1.安装WSL 通过控制面板--程序和功能--启用或关闭WIndows功能,勾选"适用于Linux的Windows子系统". 或者通过管理员权限打开 PowerShel ...
- 数据库运维实操优质文章分享(含Oracle、MySQL等) | 2023年4月刊
本文为大家整理了墨天轮数据社区2023年4月发布的优质技术文章,主题涵盖Oracle.MySQL.PostgreSQL等数据库的基础安装配置.故障处理.性能优化等日常实践操作,以及概念梳理.常用脚本. ...
- 57.dom递归退出循环的时机
递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继续调用自身,还是return:返回终止递归. 终止的条件: 1.判断递归的次数是否达到某一限定值 2.判断运算 ...
- 011 Python 的打印(花式变色打印)和注释(为什么加个#号就能注释)
#!/usr/bin/env python # -*- coding:utf-8 -*- # Datatime:2022/7/18 21:29 # Filename:011 Python 的打印和注释 ...
- 洛谷P1219八皇后问题
[USACO1.5] 八皇后 Checker Challenge 题目链接 题目描述 一个如下的 \(6 \times 6\) 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对 ...
- 利用 Kubernetes 内置 PodTemplate 管理 Jenkins 构建节点
作者:Rick Jenkins 可以很好地与 Kubernetes 集成,不管是控制器(controller)还是构建节点(agent),都能以 Pod 的形式运行在 Kubernetes 上. 熟悉 ...
- URL是什么
URL是什么 URL(Uniform Resource Locator,统一资源定位器) URL的组成: 协议://{域名|主机名|IP}:端口/路径/文件名?参数#锚点 协议 Scheme/Prot ...
- HTTP常用返回结果状态码
摘编自<图解HTTP> HTTP状态码负责表示客户端 HTTP请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作.状态码的职责是当客户端向服务器端发送请求时,描述返回的请求 ...
- 7000元才有的高性能显卡配置,ToDesk云电脑只要不到1块!
高性能显卡不仅仅是游戏玩家的刚需,也是设计师.工程师和剪辑师等专业人士的必备电脑配置.对于追求极致图形处理能力的用户来说,7000元的显卡预算并不罕见.然而,这样的花费对于大多数个人用户和小型企业来说 ...