1.简介

从这篇文章开始,就开始要介绍UI自动化核心的内容,也是最困难的部分了,就是:定位元素,并去对定位到的元素进行一系列相关的操作。想要对元素进行操作,第一步,也是最重要的一步,就是要找到这个元素,如果连元素都定位不到,后续什么操作都是无用功,都是扯淡,因此宏哥建议小伙伴或者同学们从这里开始就要跟紧宏哥的脚步,一步一个脚印的将基础打结实,不要到后期了要定位操作元素了,到处找人问到处碰壁。说到元素定位,小伙伴或者童鞋们肯定会首先想到 selenium 的八大元素定位大法。同理Playwright也有自己的元素定位的方法。今天就给小伙伴或者童鞋们讲解和分享一下Playwright的元素定位方法。其实在Python+Playwright自动化测试系列文章中也介绍过元素定位,宏哥看一下Java和Python的几乎是大同小异,只不过是Java和Python语法格式的区别,其他的大差不差。但是为了这一系列文字的完整和连贯,宏哥还是将其讲解和分享一下。

2.什么是定位?

宏哥这里说的定位和我们平时说的不一样,Playwright能够模拟用户去浏览器页面上执行对应(输入,点击,清除,提交)等操作,它是凭什么方式去寻找到页面的元素?Playwright没有视觉、听觉等。Selenium通过在页面上寻找元素位置,找到元素后,然后对元素进行相应的操作,Playwright寻找元素位置的方法,称之为定位。

3.定位器(Locator)

官网是这样对定位器进行定义的:定位器(Locator)是 Playwright 的自动等待和重试能力的核心部分。简而言之,定位器是一种随时在网页上查找元素的方法。

4.内置定位器

这些是 Playwright 推荐的内置定位器。

5.元素基础定位方式

Playwright 带有多个内置定位器。为了使测试具有弹性,我们建议优先考虑面向用户的属性和显式契约,例如 Page.getByRole()。例如:以下 DOM 结构。

按名称为“Sign in”的角色找到元素:button 。

page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign in")).click();
敲黑板!!!注意使用代码生成器生成定位器,然后根据需要进行编辑。

每次将定位器用于操作时,页面中都会找到最新的 DOM 元素。在下面的代码片段中,底层 DOM 元素将定位两次,一次在每次操作之前。这意味着,如果 DOM 在两次调用之间由于重新渲染而发生变化,则将使用与定位器对应的新元素。

Locator locator = page.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName("Sign in")) locator.hover();
locator.click();

请注意,创建定位器的所有方法(如 Page.getByLabel())也可用于 Locator 和 FrameLocator 类,因此您可以链接它们并迭代缩小定位器的范围。

Locator locator = page
.frameLocator("#my-frame")
.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign in")); locator.click();

5.1按角色定位

Page.getByRole()定位器反映了用户和辅助技术如何感知页面,例如,某个元素是按钮还是复选框。按角色定位时,通常还应传递可访问的名称,以便定位器精确定位确切的元素。例如:以下 DOM 结构。

您可以根据其隐式角色来定位每个元素:

assertThat(page
.getByRole(AriaRole.HEADING,
new Page.GetByRoleOptions().setName("Sign up")))
.isVisible(); page.getByRole(AriaRole.CHECKBOX,
new Page.GetByRoleOptions().setName("Subscribe"))
.check(); page.getByRole(AriaRole.BUTTON,
new Page.GetByRoleOptions().setName(
Pattern.compile("submit", Pattern.CASE_INSENSITIVE)))
.click();

角色定位器包括按钮、复选框、标题、链接、列表、表格等,并遵循 W3C 对 ARIA 角色、ARIA 属性和可访问名称的规范。请注意,许多 html 元素(例如)都有一个隐式定义的角色,该角色定位器可以识别该角色:<button>

请注意,角色定位器不会取代可访问性审核和一致性测试,而是提供有关 ARIA 指南的早期反馈。

敲黑板!!!注意:何时使用角色定位器:官网建议优先使用角色定位器来定位元素,因为这是最接近用户和辅助技术感知页面的方式。

5.2按标签定位

大多数表单控件通常都有专用标签,可以方便地使用这些标签与表单进行交互。在这种情况下,您可以使用 Page.getByLabel() 通过其关联标签来定位控件。例如:以下 DOM 结构。

您可以通过标签文本找到输入后填充输入:

page.getByLabel("Password").fill("secret");

敲黑板!!!注意:何时使用标签定位器:官网建议在查找表单字段时,请使用此定位器。

5.3按占位符定位

输入可能具有占位符属性,以提示用户应输入什么值。您可以使用 Page.getByPlaceholder()找到此类输入。例如:以下 DOM 结构。

您可以通过占位符文本找到输入后填充输入:

page.getByPlaceholder("name@example.com").fill("playwright@microsoft.com");

敲黑板!!!注意:何时使用占位符定位器:官网建议在查找没有标签但具有占位符文本的表单元素时,请使用此定位器。

5.4按文本定位

通过它包含的文本找到一个元素。使用 Page.getByText()时,您可以通过子字符串、精确字符串或正则表达式进行匹配。例如:以下 DOM 结构。

您可以通过它包含的文本找到该元素:

assertThat(page.getByText("Welcome, John")).isVisible();

设置完全匹配:

assertThat(page
.getByText("Welcome, John", new Page.GetByTextOptions().setExact(true)))
.isVisible();

与正则表达式匹配:

assertThat(page
.getByText(Pattern.compile("welcome, john$", Pattern.CASE_INSENSITIVE)))
.isVisible();

敲黑板!!!注意:

(1)按文本匹配始终会使空格归一化,即使完全匹配也是如此。例如,它将多个空格转换为一个空格,将换行符转换为空格,并忽略前导和尾随空格。

(2)何时使用文本定位器:官网建议建议使用文本定位器来查找非交互式元素,如div、span、p 等。对于交互式元素(如button、a、input 等),请使用角色定位器。

您还可以按文本进行筛选,这在尝试查找列表中的特定项目时非常有用。

5.5通过替代文本定位

所有图像都应具有描述图像的属性alt。您可以使用 Page.getByAltText() 根据替代文本定位图像。例如:以下 DOM 结构。

您可以通过文本替代找到图像后单击图像:

page.getByAltText("playwright logo").click();

敲黑板!!!注意,何时使用 ALT 定位器:官网建议当您的元素支持 alt 文本(如 img 和 area)时,请使用此定位器。

5.6按标题定位

使用 Page.getByTitle()找到具有匹配 title 属性的元素。例如:以下 DOM 结构。

您可以通过标题文本找到问题后检查问题计数:

assertThat(page.getByTitle("Issues count")).hasText("25 issues");

敲黑板!!!注意,何时使用标题定位器:官网建议当元素具有title属性时,请使用此定位器。

5.7按测试ID定位

通过测试 ID 进行测试是最具弹性的测试方式,因为即使您的文本或属性角色发生变化,测试仍将通过。 QA 和开发人员应定义显式测试 ID 并使用 Page.getByTestId() 查询它们。但是,通过测试 ID 进行测试不是面向用户的。如果角色或文本值对您很重要,请考虑使用面向用户的定位器,例如角色和文本定位器。例如:以下 DOM 结构。

您可以通过其测试 ID 找到该元素:

page.getByTestId("directions").click();

敲黑板!!!注意,何时使用 TESTID 定位器:官网建议当您选择使用测试 ID 方法时,或者当您无法按角色或文本进行定位时,也可以使用测试 ID。

5.7.1设置自定义的测试ID

默认情况下,Page.getByTestId()将根据属性data-testid定位元素,但您可以在测试配置中或通过调用 Selectors.setTestIdAttribute()来配置它。

将测试 ID 设置为对测试使用自定义数据属性。

playwright.selectors().setTestIdAttribute("data-pw");

在您的 html 中,您现在可以用data-pw作您的测试 ID,而不是默认的data-testid。然后像往常一样找到该元素:

page.getByTestId("directions").click();

5.8通过CSS或者Xpath定位

如果您绝对必须使用 CSS 或 XPath 定位器,则可以使用 Page.locator()创建一个定位器,该定位器采用描述如何在页面中查找元素的选择器。Playwright 支持 CSS 和 XPath 选择器,如果您省略或添加前缀css=或xpath=,则会自动检测它们。

page.locator("css=button").click();
page.locator("xpath=//button").click(); page.locator("button").click();
page.locator("//button").click();

XPath 和 CSS 选择器可以绑定到 DOM 结构或实现。当 DOM 结构发生变化时,这些选择器可能会中断。下面的长 CSS 或 XPath 链是导致测试不稳定的不良做法的一个示例:

page.locator(
"#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input"
).click(); page.locator("//*[@id='tsf']/div[2]/div[1]/div[1]/div/div[2]/input").click();

敲黑板!!!注意,何时使用此工具:官网不建议使用 CSS 和 XPath,因为 DOM 经常会更改,从而导致无法恢复的测试。取而代之的是,尝试提出一个接近用户感知页面方式的定位器,例如角色定位器,或者使用测试 ID 定义明确的测试合同。

6.阴影定位-Shadow DOM

在做web自动化的时候,一些元素在shadow-root的节点下,使得playwright中无法通过xpath来定位

上面所看到的shadow-root标签其实就是一个shadowDOM,那么什么是shadowDOM呢?

他是前端的一种页面封装技术,可以将shadowDOM视为“DOM中的DOM”(可以看成一个隐藏的DOM)

他是一个独立的DOM树,具有自己的元素和样式,与原始文档DOM完全隔离。

shadowDOM必须附在一个HTML元素中,存放shadowDOM的元素,我们可以把它称为宿主元素。在HTML5中有很多的标签样式都是通过shadowDOM来实现的。

比如:日期选择框,音频播放标签,视频播放标签都自带了样式;(这种封装对于前端开发来说虽好,但是我们测试人员在做web自动给的时候就会遇到一些问题,shadowDOM中的标签无法定位。)

默认情况下,Playwright 中的所有定位器都使用 Shadow DOM 中的元素。例外情况是:

  • 通过 XPath 定位不会刺穿阴影根部。
  • 不支持闭合模式影子根。

例如:以下自定义 Web 组件示例:

<x-details role=button aria-expanded=true aria-controls=inner-details>
<div>Title</div>
#shadow-root
<div id=inner-details>Details</div>
</x-details>

您可以采用与影子根根本不存在相同的方式进行定位。

要单击 :<div>Details</div>

page.getByText("Details").click();
<x-details role=button aria-expanded=true aria-controls=inner-details>
<div>Title</div>
#shadow-root
<div id=inner-details>Details</div>
</x-details>

点击 :<x-details>

page.locator("x-details", new Page.LocatorOptions().setHasText("Details"))
.click();
<x-details role=button aria-expanded=true aria-controls=inner-details>
<div>Title</div>
#shadow-root
<div id=inner-details>Details</div>
</x-details>

要确保包含文本“详细信息”,请执行以下操作:<x-details>

assertThat(page.locator("x-details")).containsText("Details");

7.小结

今天这一篇主要是讲解我们日常工作中在使用Playwright进行元素定位的一些比较常用的基础定位方法的理论基础知识以及在什么情况下推荐使用,当然了这不是一成不变的,希望大家在使用中可以灵活多变的应用,一种不行就换另一种说不定就可以了,不要太较真死活就要用它,一棵树上吊死。

好了,今天时间也不早了,宏哥就讲解和分享到这里,感谢您耐心的阅读,希望对您有所帮助。

《刚刚问世》系列初窥篇-Java+Playwright自动化测试-6- 元素基础定位方式-上篇 (详细教程)的更多相关文章

  1. 《手把手教你》系列技巧篇(四十七)-java+ selenium自动化测试-判断元素是否显示(详解教程)

    1.简介 webdriver有三种判断元素状态的方法,分别是isEnabled,isSelected 和 isDisplayed,其中isSelected在前面的内容中已经简单的介绍了,isSelec ...

  2. 《手把手教你》系列技巧篇(四十八)-java+ selenium自动化测试-判断元素是否可操作(详解教程)

    1.简介 webdriver有三种判断元素状态的方法,分别是isEnabled,isSelected 和 isDisplayed,其中isSelected在前面的内容中已经简单的介绍了,isSelec ...

  3. 《手把手教你》系列基础篇之(一)-java+ selenium自动化测试-环境搭建(上)(详细教程)

    1.简介 jmeter系列的文章结束,本来想趁热打铁顺别将Jmeter和接口测试介绍一下,但是感觉Jmeter时间太长了怕大家吃腻了,还有一个原因就是许多小伙伴们或者童鞋们私信问宏哥什么时候可以有ja ...

  4. 《手把手教你》系列基础篇(五)-java+ selenium自动化测试- 创建首个自动化脚本(详细教程)

    1.简介 前面几篇宏哥介绍了两种(java和maven)环境搭建和三大浏览器的启动方法,这篇文章宏哥将要介绍第一个自动化测试脚本.前边环境都搭建成功了,浏览器也驱动成功了,那么我们不着急学习其他内容, ...

  5. 《手把手教你》系列技巧篇(二十八)-java+ selenium自动化测试-处理模态对话框弹窗(详解教程)

    1.简介 在前边的文章中窗口句柄切换宏哥介绍了switchTo方法,这篇继续介绍switchTo中关于处理alert弹窗的问题.很多时候,我们进入一个网站,就会弹窗一个alert框,有些我们直接关闭, ...

  6. 《手把手教你》系列技巧篇(三十二)-java+ selenium自动化测试-select 下拉框(详解教程)

    1.简介 在实际自动化测试过程中,我们也避免不了会遇到下拉选择的测试,因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助. 2.select 下拉框 2.1Select ...

  7. 《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)

    1.简介 上一篇介绍了POM的基础理论知识和非POM方式写脚本,这篇介绍利用页面工厂类(page factory)去实现POM,通过查看PageFactory类,我们可以知道它是一个初始化一个页面实例 ...

  8. 《手把手教你》系列基础篇(七十七)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试- 上篇(详解教程)

    1.简介 今天主要是讲解和分享:TestNG中一个类中有多个测试方法的时候,多个测试方法的执行顺序或者依赖关系的问题.如果不用dependsOnMethods,testNG会自动根据@Test方法名称 ...

  9. spring 5.x 系列第6篇 —— 整合 mybatis + druid 连接池 (代码配置方式)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 项目目录结构 1.创建maven工程,除了Spring基本依赖外,还需要导 ...

  10. spring 5.x 系列第5篇 —— 整合 mybatis + druid 连接池 (xml配置方式)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 项目目录结构 1.创建maven工程,除了Spring基本依赖外,还需要导 ...

随机推荐

  1. Error:java: JDK isn't specified for module

    报错: Error:java: JDK isn't specified for module 背景: 删除原项目文件夹内所有文件,copy的新的配置文件与src文件夹等,期间打开该项目的IDEA一直处 ...

  2. Jenkins 运行pipeline 报错:A Jenkins administrator will need to approve this script before it can be us

    之前没有注意过这个问题,是因为之前运行pipeline时,默认勾选了"使用 Groovy 沙盒" 这次不小心取消了勾选导致,重新加上勾选即可

  3. 【YashanDB知识库】yasql登录报错:YAS-00413

    [问题分类]错误码处理 [关键字]yasql,00413 [问题描述]使用工具设置不同并发迁移数据的过程中,导致yasql登录报错:YAS-00413 [问题原因分析]工具使用与数据库使用资源超过了操 ...

  4. Linux IP 命令

    改MAC 地址 ip link set dev nic1 downip link set dev nic1 address 0c:42:a1:8f:a4:47ip link set dev nic1 ...

  5. jstack排查cpu占用高的步骤

    通过jstack排查cpu占用高的问题 1.通过top命令找到cpu占用高的应用程序进程 2.通过top -H -p pid查看该应用中占用CPU高的线程. 3.通过printf "%x\n ...

  6. 使用 Microsoft.Extensions.ServiceDiscovery 进行服务发现并调用

    简介 在现代微服务架构中,服务发现(Service Discovery)是一项关键功能.它允许微服务动态地找到彼此,而无需依赖硬编码的地址.以前如果你搜 .NET Service Discovery, ...

  7. Flutter 3.3 正式发布

    Flutter 3 是我们正式为全平台提供支持的一个重量级里程碑,距离它的发布仅过去了三个月,今天让我们有请 Flutter 3.3 正式版!近三个月我们并没有放慢更新迭代的速度--自 Flutter ...

  8. Dockerfile定制镜像(FROM?RUN ?WORKDIR ?ADD & COPY指令)(七)

    一.Dockerfile 镜像的定制实际上就是定制镜像的每一层所添加的配置.文件等信息,实际上当我们在一个容器中添加或者修改了一些文件后,我们可以通过docker commit命令来生成一个新的镜像, ...

  9. OOP的核心思想

    1. 封装 既是信息封装,把一些信息进行封装成对象,只保留部分接口和方法与外部联系,能有效避免程序间相互依赖,实现代码模块间松藕合 : 2. 继承 子类自动继承父类的属性和方法,继承实现了代码的重用性 ...

  10. 云原生周刊:Helm Charts 深入探究 | 2024.3.11

    开源项目推荐 Glasskube Glasskube 提供了一个用于 Kubernetes 的缺失的包管理器.它具有图形用户界面(GUI)和命令行界面(CLI).Glasskube 包是具备依赖感知. ...