高级定位-XPath
上一节课我们学习了 CSS 定位的使用方法,本节课我们将进一步探索另一种高级定位方式——XPath。和 CSS 定位一样,XPath 也是一种强大的元素定位工具,但它的语法和使用场景稍有不同,非常适合处理复杂的结构和特定需求。
简介
XPath
是一种用于在 XML
文档中检索信息的语言。它通过路径表达式导航 XML
文档,广泛应用于各种场景。XPath
的灵活性和强大功能使其成为在 XML
结构中准确定位和提取数据的重要工具。
那让我们先来认识认识什么是 XPath,它是一种专门用来在 XML 文档中检索信息的语言。XPath 的核心功能是通过路径表达式导航 XML 文档的结构,从而快速找到我们需要的节点或数据。由于它灵活而强大,不仅在 XML 中用得多,像 HTML 页面这种树形结构中,我们也经常用它来定位元素。简单来说,XPath 是处理复杂结构化数据的利器,非常值得掌握。
XPath 使用场景
- Web 自动化测试:
XPath
在Web
自动化测试中广泛应用,XPath
提供了一种强大的定位方式。它能够通过元素的层次结构、属性、文本内容等进行更加灵活和精准的定位,适用于各种复杂的 Web 应用页面。
- App 自动化测试:
- 在移动应用的自动化测试中,
XPath
可以在原生应用和混合应用(Hybrid App
)中定位和操作元素。在App
的UI
中,XPath
可以针对不同平台(如iOS
和Android
)提供一致的选择能力,使测试脚本更具通用性。
- 在移动应用的自动化测试中,
我们再来看看 XPath 的实际使用场景。刚才咱们提到了,在 Web 自动化测试中,XPath 是一种非常强大的定位方式。它不仅能根据元素的层次结构来定位,还支持通过属性、文本内容等进行更加灵活和精准的选择,尤其在处理复杂的 Web 页面时特别好用。此外,在 App 自动化测试中,XPath 同样表现出色。所以无论是原生应用还是混合应用,XPath 都能帮助我们定位和操作界面元素。而且,它可以在不同平台间提供一致的定位能力,比如 iOS 和 Android,这使得测试脚本具有更高的通用性。
XPath 相对定位的优点
- 可维护性更强:XPath 相对定位可以相对于其他元素的方式来定位元素。如果页面结构发生变化,只需要更新相对路径中的某些部分,而不必重新创建整个定位表达式。
- 语法更加简洁:XPath 相对路径是相对于其他元素的路径,更容易理解和编写。与复杂的绝对路径相比,相对路径语法更加简洁。
- 相比于 css 可以支持更多的方式:XPath 相对定位可以访问 XML 和 HTML 文档的任何部分,而不仅仅是元素和属性。
说完了 XPath 的使用场景后,相信大家也基本了解到了,XPath 相对定位具有非常多的优点。第一,可维护性强。相对定位的最大特点就是可以相对于其他元素来定位目标元素。如果页面的结构发生变化,只需要调整路径中某些部分,而不是重写整个表达式,这大大降低了维护成本。第二,语法简洁明了。相对路径通常比绝对路径更短,更容易理解和编写,特别是在处理复杂页面时,简洁的表达式让定位逻辑一目了然。最后,功能更强大。和 CSS 定位相比,XPath 不仅能定位元素和属性,还能直接访问 XML 和 HTML 文档的任意部分,比如文本节点。这种灵活性让它在很多场景下有明显的优势。总的来说,XPath 的相对定位是一种高效又灵活的选择,适用于各种复杂的自动化测试需求。
示例代码如下:
# 复制的绝对定位
$x('//*[@id="ember75"]/td[1]/span/a')
# 编写的相对定位
$x("//*[text()='技术分享 | SeleniumIDE用例录制']")
了解完了 XPath 的基本语法和应用场景后,让我们来看一下代码示例,直观感受 XPath 相对定位和绝对定位的区别。首先是绝对定位,这段代码是从根节点开始逐层定位到目标元素。如果页面结构发生变化,比如某个父元素被修改或移除,这个定位就会失效,维护起来比较麻烦。再来看下面的相对定位,它直接通过目标元素的文本内容进行定位,而不是依赖层级结构。这种写法不仅更简洁,还具有很高的容错率,即使页面结构调整了,只要文本内容没变,定位就依然有效。这个对比就很好地展示了相对定位的优势,简洁、灵活、同时更适合复杂页面的自动化测试。
XPath 定位的调试方式
浏览器-console:$x("XPath 表达式")。
我们在实际工作中,常常需要验证 XPath 表达式的正确定,这个时候浏览器的 console 就是一个非常好的工具。在控制台输入表达式,如果没有返回结果,那可能就是表达式有问题,和验证 css 定位一样,这是我们需要重点关注的,是日常开发和测试中必不可少的技能。
浏览器-elements:ctrl+f 输入 XPath 或者 css。
除了我们熟知的控制台,还有另一个常用的调试方式,就是直接在浏览器的 Elements 面板中操作,这个方法特别适合快速验证 XPath 或 CSS 选择器。操作方式为打开浏览器的开发者工具,在 Elements 面板按下 Ctrl+F 或者 macos 为 command + F,会出现一个输入框。在这里输入你的 XPath 表达式或者 CSS 选择器,浏览器就会高亮匹配到的元素。这种方式更加简单直观,能快速确认表达式是否正确定位到了目标元素,非常适合初步测试你的定位逻辑。建议大家熟练掌握这个方法,它能极大地提高调试效率。
XPath 基础语法(包含关系)
表达式 | 结果 |
---|---|
/ | 从该节点的子元素选取 |
// | 从该节点的子孙元素选取 |
* | 通配符 |
nodename | 选取此节点的所有子节点 |
.. |
选取当前节点的父节点 |
@ | 选取属性 |
我们再来看一下 XPath 的基础语法,特别是一些常用的包含关系操作。掌握这些表达式后,你可以更加灵活地定位元素。第一个,单斜杠:表示从某个节点的直接子元素中选取,比如 杠div 就是当前节点下的所有 div 子元素。第二个双斜杠:表示从某个节点的所有子孙元素中选取,不限层级,比如 杠杠span 会找到所有的 span 元素,不管嵌套有多深。第三个,星号,这是通配符,用来匹配所有元素,常见的用法是 杠杠 div 杠 星号,表示选取某个 div 下的所有子元素。第四个,node name:直接选取当前节点的所有子节点,比如 div 就是选择所有的 div 节点。第五个,点点:用来选取当前节点的父节点,在需要反向查找时很有用。最后一个 @ :用来选取属性,比如 杠杠@class,就是选取所有的 class 属性。这些基础语法虽然简单,但组合起来就能解决很多复杂的定位需求。建议大家熟悉每一条的用法,然后结合实际场景去应用。
XPath 基础语法实战
打开测试人社区(https://ceshiren.com/),F12 进入开发者模式,选择 console
那么我们了解了基本语法以后,就来做一下实战吧,还是测试人社区为例。
整个页面
$x("/")
如果你想直接选取整个页面的根节点,可以用 刀了符 x 括号 双引号 杠 这个表达式。它的作用是返回文档的根节点,在标准 HTML 页面中通常就是 html 标签。这是 XPath 中最顶层的定位方式,非常适合在需要从文档入口点开始分析整个页面结构时使用。它只会返回一个根节点,这也说明了它的定位范围是整个文档的起点。
整个页面中的第一层元素
$x("/*")
如果你想获取整个页面中的所有顶层元素,可以用这个简单的表达式:刀了符 x 括号 双引号 杠 星号。它的含义是选取文档的根节点下面的所有直接子元素。比如在一个标准的 HTML 页面中,这通常会返回 html 标签,因为它是根节点下的唯一顶层元素。这个写法虽然看起来简单,但在调试时很实用,特别是在需要从根节点开始探索页面结构的时候,能快速帮你明确当前文档的层级关系。
整个页面中的所有元素
$x("//*")
杠星 代表整个页面的所有顶层元素,那么杠杠星就代表整个页面的所有元素,它的意思就是从根节点开始,选取文档中所有的元素节点,在标准的 HTML 页面中,它会遍历html、head、body以及它们的所有子孙元素,最终返回页面中的每一个标签节点,就是是所有元素了。在调试的时候,这个表达式非常适合用来快速查看页面的整体结构,当不确定元素的具体层级的时候,可以通过这种方式一次性获取所有节点,方便后续筛选。
查找页面上所有的 div 标签节点
$x("//div")
如果你想查找页面上所有的 div 标签节点,可以使用 刀了符 x 括号双引号 杠杠 div。这个表达式的作用是从根节点开始,找到文档中所有的 div 元素,无论它们位于页面结构的哪个层级。比如,你可以用它快速筛选出页面中所有的容器、布局元素,方便进一步操作或者调试。在浏览器的 console 中输入这个表达式,你会看到所有匹配的 div 节点会被列出。通过这种方式,你可以直观了解页面中 div 标签的分布和层次。
查找 id 属性为 site-logo 的节点
$x('//*[@id="site-logo"]')
接着是使用id属性来查找元素,比如你想找到 id 属性为 site-logo 的节点,就可以写成 刀了符 x 括号 双引号 杠杠星 中括号 艾特id = site-logo,这里的 艾特id="site-logo" 表示通过 id 属性值精确定位元素,而前面的 杠杠星 意味着在整个页面中查找任意类型的元素。这个写法非常常见,尤其是在处理唯一 id 的节点时,它既简单又高效。
查找节点的父节点
$x('//*[@id="site-logo"]/..')
如果需要找到某个节点的父节点,就可以使用 杠点点 这个语法,比如刚才咱们找到的id=site-logo的父节点,在后面加上 杠点点 就可以获取到它的父节点,接下来大家可以试试,多做一些练习,比如使用 id或name等其他属性值来找到任意对应节点,然后再通过 杠点点 来获取父节点。
XPath 顺序关系(索引)
XPath 通过索引直接获取对应元素:
# 获取此节点下的所有的li元素
$x("//*[@id='ember21']//li")
# 获取此节点下【所有的节点的】第一个li元素
$x("//*[@id='ember21']//li[1]")
我们继续讲解关于 XPath 顺序关系,也可以称为索引。在 XPath 中,我们可以通过索引直接获取特定的元素,这种方式简单明了,特别适合定位同类型元素中的某一个。比如第一个表达式,会获取 id 为 ember21 的节点下所有的 li 元素。这种写法可以返回一个列表,包含所有匹配的 li 标签。而如果你只想获取这些 li 元素中的第一个,可以在表达式末尾加上索引 [1],像第二行表达式那样。它表示只取匹配结果中的第一个 li。这种基于索引的定位方式非常灵活,适合处理类似的列表、菜单等结构。
XPath 高级用法
语法 | 含义 |
---|---|
[last()] |
选取最后一个 |
[@属性名='属性值' and @属性名='属性值'] |
与关系 |
[@属性名='属性值' or @属性名='属性值'] |
或关系 |
[text()='文本信息'] |
根据文本信息定位 |
[contains(text(),'文本信息')] |
根据文本信息包含定位 |
注意:所有的表达式需要和[] 结合。 |
接下来我们看看 XPath 的一些高级用法,这些语法可以让定位更精准、更灵活:第一个, 方括号 last 小括号:这个用法可以直接选取匹配结果中的最后一个元素。第二个:中括号 @属性名='属性值' and @属性名='属性值':表示 ,与, 关系,需要同时满足多个条件。第三个,中括号 @属性名='属性值' or @属性名='属性值':表示,或,关系,满足其中任意一个条件即可。第四个,中括号 text括号='文本信息':通过元素的文本内容进行精确匹配,适合定位那些显示特定文本的标签。第五个,中括号 contains 小括号,text小括号,加引号加文本信息:当你只知道部分文本内容时,可以用这个包含关系。需要注意的是,这些高级表达式通常需要配合 中括号 使用,它们能够极大地增强定位的灵活性。建议大家多练习,结合实际场景用这些技巧快速找到目标元素。
XPath 高级用法实战
打开测试人社区(https://ceshiren.com/),F12 进入开发者模式。
接下来让我进入 XPath 的实战练习。
选取最新的元素
选取最后一个 div 标签
$x("(//div)[last()]")
如果你想选取页面中最新的元素,比如最后一个 div 标签,可以使用 刀了符 x 小括号 引号 小括号 杠杠div 中括号 last 小括号。这里 杠杠div 表示选取页面中所有的 div 元素,而 last小括号 会返回匹配结果中的最后一个 div,也就是页面结构中最靠后的一个。这种写法特别适合在动态页面中使用,比如页面会不断生成新的元素时,可以通过 last 快速定位到最新添加的那个元素。试试看在浏览器的 console 输入这段代码,就能直接获取到页面中的最后一个 div。
多个属性共同定位-交集
选取属性 id 的值为 ember24 并且属性 class 的值为 nav-item_new new ember-view 的 input 标签
$x("//*[@class='nav-item_new new ember-view' and @id ='ember24']")
当需要通过多个属性同时定位某个元素时,可以使用交集方式,结合 and 运算符来实现。比如,这段表达式 就是一个经典的例子,前面的 艾特class 表示匹配 class 属性值为 该值的元素;而 后面的 @id='ember24' 表示匹配 id 属性值为 ember24 的元素。and 运算符确保了只有同时满足这两个条件的元素才会被选中。这个用法非常适合在页面中有多个类似结构但又需要精确区分时使用,比如导航菜单、重复模块等。
多属性共同定位-并集
选取属性 id 的值为 ember24 或属性 id 的值为 ember23 的 input 标签
$x("//*[@id='ember23' or @id ='ember24']")
如果想通过多个属性值的‘或’关系来定位元素,可以使用 or 运算符,让表达式更灵活。比如这段表达式,它会选取 id 属性值为 ember23 或 id 属性值为 ember24 的所有元素;并且无需两者条件同时满足,只要符合其中之一,就会被选中。这种写法非常适合在页面中有多个备选目标时使用,比如你不确定最终需要哪个元素,但都希望捕获的话。
文本信息定位
选取所有文本信息为'所有类别'的元素
$x(' //*[text()="所有类别"]')
如果想通过元素的文本内容来定位,可以使用 text 函数。比如这段代码,它的意思是:杠杠星中括号 text 小括号 等于 所有类别, 会找到页面中所有文本内容完全等于 所有类别 的元素;星号表示不限制标签类型,只要符合条件的元素都会被选中。这种方式非常适合用于静态文本内容的定位,比如按钮、标题或者固定的标签内容。
文本信息包含定位
选取所有文本信息包'Python 测试开发'的元素
$x('//*[contains(text(),"Python测试开发")]')
当然,如果当我们不知道全部文本内容,只知道部分文本内容时,还可以使用 contains 函数来进行包含定位。比如这段表达式,杠杠星 contains 小括号,text函数,Python测试开发 这段表达式,会找到页面中所有文本内容包含 Python测试开发 的元素;和 text()="某文本" 不同的是,它不要求完全匹配,只要文本中包含这个关键字,就会被选中。这个方法特别适合处理动态生成的文本或者部分固定的内容,比如文章标题或提示信息。
Xpath 定位-实战
测试步骤
- 打开测试人社区(https://ceshiren.com/)
- 使用 XPath 高级定位,进入【类别】的页面。
- 获取文本值进行断言。
学习完了XPath 高级定位,现在来实战一下。和 CSS 的实战练习一样,我们这次换成使用 XPath 定位方式来定位元素。
Python 实现
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
class Test():
def setup(self):
service = Service()
options = webdriver.ChromeOptions()
self.driver = webdriver.Chrome(service=service,options=options)
self.driver.implicitly_wait(10)
def teardown(self):
self.driver.quit()
def test_xpath(self):
self.driver.get("https://www.ceshiren.com")
self.driver.find_element(By.XPATH,"//*[text()='类别']").click()
text = self.driver.find_element(By.XPATH,"//*[text()='提问区']").text
assert text == '提问区'
希望大家可以自己动手敲一下具体实现代码,Python 版本的实现就如下所示,首先创建driver 实例,然后打开测试人社区网页,通过 XPath 定位方式定位到文本值为类别的元素,然后点击该元素,接着获取文本值为提问区的元素,并获取文本值,最后进行断言。
总结
XPath定位是一种非常便捷的方法,不仅可以通过常规的id、class等属性进行元素定位,还可以通过父子关系和后代关系来实现更灵活的定位。这使得XPath在元素选择和定位方面具有独特的优势。
通过今天的学习我们了解了高级定位方式 XPath,XPath 定位是一种功能强大的方法,大家可以看到它的功能非常强大,应用场景广泛,优点非常多,不仅支持通过常规的 id、class 等属性进行元素定位,还可以利用父子关系、后代关系等结构化的路径来实现更复杂和灵活的定位需求。这种多样化的定位方式让 XPath 成为在自动化测试中不可或缺的工具,不管是面对简单的页面元素还是复杂的层次结构,它都能应对自如,让元素选择更高效、更精准,所以大家一定要掌握好这种定位方式,在以后的学习中,我们会经常使用到,所以大家要多多练习实践,打牢基本功。