高级定位 - CSS
同学们大家好,今天这个章节我们来学习自动化测试中,8种定位方式之一的高级定位,CS S 定位。
简介
Web 自动化测试中的高级 CSS 定位是指使用复杂的 CSS 选择器来选择页面上的元素,以便在自动化测试中与这些元素进行交互。
CSS 定位可以分为 相对定位
和 绝对定位
。
可以根据元素的标签、类、ID、属性、关系和状态等多种因素进行定位。高级 CSS 定位不仅允许你选择单个元素,还可以选择元素的集合,从而更好地适应不同的测试场景。和 Xpath 一块常用于 UI 自动化测试中的元素定位。
在本章节中,我们将学习高级 CS S 定位在 Web 自动化测试中的应用。我们先来看下 CS S 定位有哪些优点,它具有高效、灵活的特点,可以通过标签、类、ID、属性等多种方式精确地定位页面元素,并进行交互。那么我们通过掌握相对定位和绝对定位的方法,就能够更高效地选择元素集合,满足不同的自动化测试需求。在实践中,结合 XPath 一同使用,可以更好地应对各种复杂的测试场景,提升测试的稳定性与可维护性。
css 相对定位使用场景
- 适用于 Web 产品,能够提供更灵活的元素定位和布局方式。
- 在支持 WebView 的 App 端,相对定位同样发挥作用,确保元素在移动端的用户界面中能够按照预期进行定位和排列。
接下来我们再来看看 CS S 相对定位的使用场景。相对定位在 Web 产品中提供了更加灵活的元素定位和布局方式,能够根据元素本身的位置来进行定位,从而在复杂布局下也能够确保定位的精确性。此外,相对定位在支持 WebView 的 App 端同样具有重要作用,能够确保移动端界面中的元素按照预期排列和定位,使得测试在不同设备和平台上的稳定性得以保障。这种定位方式在自动化测试中是非常实用的,尤其是在响应式设计和动态页面中,能够提高定位的精准度和适应性。
css 相对定位的优点
# 绝对定位
$("#ember63 > td.main-link.clearfix.topic-list-data > span > span > a")
# 相对定位
$("#ember63 [title='新话题']")
- 相对定位更易于维护,当页面结构发生变化时,绝对定位可能需要更新所有的选择器,而相对定位只需要更新相关的选择器。
- 相对定位通常比绝对定位更简洁明了,使代码更易于阅读和理解。
- 在某些情况下,页面中的元素可能嵌套在多个层次的父元素中,这时相对定位可以更轻松地选择目标元素,而无需编写冗长的选择器。
让我们再来看看 CS S 相对定位的优点。刚才我们提到过它的高效和灵活性,接下来我会详细说明它和绝对定位相比的几个明显优点。首先,相对定位的选择器往往更简洁、更易于理解,也更方便维护。这样一来,当页面结构有所变化时,我们的测试脚本更新就变得轻松多了,通常只需要修改其中一部分选择器,而不是重新构建整个选择器链条。相比之下,绝对定位可能就没那么友好了,它可能需要我们重写所有的选择器,麻烦又耗时。更重要的是,相对定位非常适合处理复杂页面中的元素,它能够轻松应对多层嵌套的情况,避免了那些冗长复杂的选择器,使得我们的代码更加简洁、可维护,并且增加了灵活性。所以,相对定位在很多情况下,无疑是一个更优的选择。
css 定位的调试方式
F12 进入浏览器的开发者模块,选择 console
,按照如下语法输入 css
表达式:
在实际测试中,我们经常需要调试 CS S 定位,而浏览器的开发者工具可以帮我们轻松实现这一点。只需要按下 F十二 打开浏览器的开发者工具,然后切换到 Console 标签页,你就可以输入 CS S 表达式来快速定位元素。常用的调试语法使用 $加括号加css 表达式构成,这可以返回所有符合条件的元素。这样,我们就能快速验证我们的选择器是否有效,确保自动化测试中的定位操作是准确的。
css 基础语法
类型 | 表达式 |
---|---|
标签 | 标签名 |
类 | .class 属性值 |
ID | #id 属性值 |
属性 | [属性名="属性值"] |
# 在console中的写法
# https://www.baidu.com/
# 标签名
$('input')
# .类属性值
$('.s_ipt')
# #id属性值
$('#kw')
# [属性名='属性值']
$('[name="wd"]')
好,这里我们进入 CSS 的基础语法部分。在表格中给大家清晰地展示了四种常见的选择器类型,包括,标签、类、ID和属性。每种类型对应不同的写法,比如标签选择器就是直接写标签名,类选择器前面加一个点,ID选择器用井号开头,属性选择器则是用方括号括起来属性和值的组合。举个例子,比如我们在浏览器的console中操作,访问百度首页,我们可以用标签选择器直接选中所有的 input 标签,写法是 刀了符 括号 加input;如果要选中类名为 s_ipt 的元素,就用类选择器,写成 刀了符 加 括号加点 s_ipt;同理,选中ID为 kw 的元素,写作 刀了符 加 括号 加 井号 kw;如果我们知道一个元素的属性,比如 name="wd",就可以用属性选择器写成 刀了符 加 括号加中括号加 name="wd"。这些基础写法特别常用,等我们熟悉了,后面还可以结合不同的选择器来实现更复杂的匹配。
css 基础语法实战
打开测试人社区(https://ceshiren.com/),F12 进入开发者模式,选择 console
接下来让我们进入实战,进行一下实际操作,首先,我们可以打开测试人社区的网站。然后,按下键盘上的 F十二 进入浏览器的开发者模式,选择里面的 console 面板。这里是我们可以直接写代码并与页面进行交互的地方,也是验证CSS选择器的好工具。
标签名
查找页面中所有的 div
标签
$("div")
接下来我们来看标签名选择器的实际使用方法。假设我们想查找页面中所有的 div 标签,可以在 console 面板中输入 刀了符 加 括号 div,这样就会返回页面上所有的 div 元素。
查找页面中所有的 a
标签
$("a")
同样的,如果我们想获取页面中所有的 a 标签,也就是超链接元素,只需要输入 刀了符 加 括号 a。这种方法简单直接,非常适合快速定位某一类标签,用起来特别方便。大家可以试着在页面上操作一下,看看返回的结果都有哪些。
.class 属性值
定位测试人社区 Logo
$(".logo-big")
同样的,我们再来看看另一个类选择器,比如我们想定位测试人社区的 Logo,可以使用它的class属性,写成 刀了符 加 括号 加 点 logo-big。
- 页面元素:
页面元素如图所示。
- console 调试:
接着我们来说一下在 console 中调试的细节。比如,当你需要查找某个类名的元素时,直接在 console 输入选择器代码即可。
- 页面元素:
页面元素如图所示。
注意:当 class 属性值有多个时,将中间的空格替换成 .
。
$(".header-dropdown-toggle.search-dropdown")
不过这里要注意一个细节——当一个元素的 class 属性值有多个,也就是有多个类名时,这些类名之间通常用空格分隔。在选择器中,我们需要把这些空格替换成 点,也就是点号,才能正确匹配到元素。
- console 调试:
大家可以参考图片中的示例,按照这个规则试着去查找页面上的元素,这种方式在实际调试中特别实用。
#id 属性值
定位测试人社区 Logo
$("#site-logo")
我们再来看看使用id来定位,还拿logo来举例,要使用它的 id 属性,我们需要把定位写成 刀了符 加 括号 加 井号 site-logo。
- 页面元素:
页面元素如图所示。
- console 调试:
控制台调试写法如图所示。
[属性名="属性值"]
定位测试人社区 Logo
$("[alt='测试人社区']")
最后我们再来看看属性选择器的用法。还是拿logo举例,它有一个属性是 alt="测试人社区"。在 console 中,我们只需要输入 刀了符 加 括号 然后加上中括号,再加上它的属性名 alt 和 属性值测试人社区,就可以精确匹配到这个 Logo 元素。属性选择器的好处是可以通过具体的属性值来锁定某些特定的元素,非常适合处理那些没有唯一类名或 ID 的情况。大家可以试试这段代码,观察一下返回的结果是不是我们想要的 Logo 元素。
- 页面元素:
页面元素如图所示。
- console 调试:
控制台调试写法如图所示。
css 关系定位
类型 | 格式 |
---|---|
并集 | 元素,元素 |
邻近兄弟(了解即可) | 元素+元素 |
兄弟(了解即可) | 元素 1~元素 2 |
父子(重点) | 元素>元素 |
后代(重点) | 元素 元素 |
# 在console中的写法
# 元素,元素
$('.bg,.s_ipt_wr,.new-pmd,.quickdelete-wrap')
# 元素>元素
$('#s_kw_wrap>input')
# 元素 元素
$('#form input')
# 元素+元素,了解即可
$('.soutu-btn+input')
# 元素1~元素2,了解即可
$('.soutu-btn~i')
接下来我们讲一下 CSS 选择器中的关系定位。这里有几种常见的类型:并集、邻近兄弟、兄弟、父子和后代。我们重点关注的是父子关系和后代关系,因为它们在实际工作中使用非常频繁。来看具体的写法,首先是并集:写法是用逗号分隔多个元素,可以同时选中多个类名对应的元素。然后是父子:用 > 表示,示例写法表示查找父元素下直接的子元素 input。接着是后代:用空格表示,示例写法表示在 #form 这个元素下的所有后代 input 元素。另外还有两种是了解即可的:第一个是邻近兄弟:用 加号,比如示例写法,表示查找紧跟在 点 soutu-btn 之后的兄弟元素 input。第二个是兄弟:用 波浪号,比如 示例写法,表示查找 点 soutu-btn 之后的所有兄弟元素 i。大家可以把这些代码在 console 中试试,特别是父子和后代关系,多练习一下,后面会用得非常多。
css 关系定位实战
打开测试人社区(https://ceshiren.com/),F12 进入开发者模式。
那了解完了css的关系定位的基础知识以后,就让我们来做一个实战,巩固一下我们的学习成果。我们依旧以测试人社区的页面来做练习,首先打开测试人社区,接着按F十二进入浏览器的开发者模式。
并集
# 会查找到页面中 id 为 `main` 的单个元素。
$("#main")
# 会查找到页面中 id 为 `ember6` 的单个元素。
$("#ember6")
# 会查找到页面中 id 为 `main` 和 `ember6` 两个元素。
$("#main,#ember6")
先看一下并集的练习,要求我们找出页面中id为main和ember6的元素,那么就让我们练习一下,大家一定要动手去做,不然只有理论知识是记不牢的。
实现如下:
相信大家都已经做完了,那么来看一下图中示例的具体的实现吧。
父子
# 会查找到页面 id 为 main 的元素
$("#main")
# 会查找到页面 id 为 ember4 的元素
$("#ember4")
# 通过父元素找子元素
$("#main>#ember4")
然后是父子关系的练习,首先我们可以找到id为main的元素,然后找到id为ember4的元素,然后通过父元素找子元素,也就是通过id为main的元素,找到该父元素下id为ember4的子元素。
写完后,是不是感觉已经基本掌握了CSS定位的写法了呢,那么我们就继续往下看吧。
后代
# 会查找到页面 id 为 main-outlet-wrapper 的元素
$("#main-outlet-wrapper")
# 会查找到页面 id 为 ember476 的元素
$("#ember476")
#main-outlet-wrapper 的后代元素
$("#main-outlet-wrapper #ember476")
这种写法非常适合复杂页面的元素定位,特别是在需要精确匹配层级关系时,那么大家来继续练习吧。
相信这三个练习对大家来说也是轻而易举的,那么关系定位的练习就先做到这里,不过大家依然需要多加练习,这样才能做到熟记于心。那么接下来我们继续进行顺序关系的练习吧。
css 顺序关系
类型 | 格式 |
---|---|
父子关系+顺序 | 元素 元素 |
父子关系+标签类型+顺序 | 元素 元素 |
# :nth-child(n)
$('#form>input:nth-child(2)')
# :nth-of-type(n)
$('#form>input:nth-of-type(1)')
顺序关系有两种写法,第一种是父子关系加顺序,比如示例写法,表示查找父元素下第 2 个 input 元素。第二种是父子关系加标签类型加顺序,比如示例写法,表示查找父元素下第一个 input 元素。这两种写法都是在处理同一个父元素下有多个不同类型的子元素,特别是第二种nth-of-type。能够够好地避免误选,大家可以试着对比这两种写法的返回结果,看看具体差别。
css 顺序关系实战
打开测试人社区(https://ceshiren.com/),F12 进入开发者模式。
我们再来做下顺序关系的练习,还是和之前一样,打开测试人社区,然后进入开发者模式。
:nth-child(n)
用于选择元素集合中的第 n 个元素,其中 n 是一个整数。如果想要精确查找,需要保证所查找到的元素是同一个父元素中的。
首先来看下第一个顺序关系选择器,nth杠child(n),这种写法用来精确定位某个父元素下特定顺序的子元素。
# 会查找到页面 id 为 ember15 的元素
$("#ember15")
# 会查找到页面 id 为 navigation-bar 的元素
$("#navigation-bar")
# 会查找到页面 id 为 ember15 元素下的直接子元素中 id 为 navigation-bar 的元素
$("#ember15>#navigation-bar")
# 选择第3个 li 标签
$("#ember15>#navigation-bar>li:nth-child(3)")
同样的,我们可以通过找到id为ember15的父元素,然后再找到它下面的id为navigation-bar的子元素,那么我们还可以加入顺序关系选择器,比如nth-child(3),就可以找到第3个li标签。
:nth-of-type(n)
用于选择某个父元素下特定类型的子元素中的第 n 个元素,其中 n 是一个整数。
- 页面元素:
接下来再来看看顺序关系的另一个写法,nth-of-type(n),这种写法用来精确定位某个父元素下特定类型的子元素中的第 n 个元素。
- console 调试:
来看一下具体写法,比如我们想找到ember15这个父元素下的第一个 ul 元素,就可以按照图中示例这样写。
CSS 定位-实战
测试步骤
- 打开测试人社区(https://ceshiren.com/)
- 使用 css 高级定位,进入【类别】的页面。
- 获取文本值进行断言。
学习完了关系定位以及顺序定位后,我们来做一个综合性的实战练习,要求我们获取文本值进行断言,具体测试步骤为首先打开测试人社区,然后使用 css 高级定位,进入【类别】的页面,最后获取文本值进行断言。
Python 实现
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
class Test:
def setup(self):
self.service = Service()
self.options = webdriver.ChromeOptions()
# 初始化 driver
self.driver = webdriver.Chrome(service=self.service, options=self.options)
# 设置隐式等待
self.driver.implicitly_wait(10)
def teardown(self):
# 退出浏览器
self.driver.quit()
def test_get_ceshiren(self):
# 进入 测试人 社区
self.driver.get("https://www.ceshiren.com")
# 查找并点击 “类别”
self.driver.find_element(By.CSS_SELECTOR,".categories").click()
# 获取类别下的文本值
text = self.driver.find_elements(By.CSS_SELECTOR,".category-name")[0].text
# 断言
assert text == "提问区"
那么接下来就是Python与Java两种不同语言的代码示例,基本实现的逻辑是一致的,大家可以自行对比。
Java 实现
public class Test {
// 初始化方法
public void setup() {
// 设置 ChromeDriver 路径 (需要根据实际路径修改)
System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
ChromeOptions options = new ChromeOptions();
// 初始化 driver
driver = new ChromeDriver(options);
// 设置隐式等待
driver.manage().timeouts().implicitlyWait(java.time.Duration.ofSeconds(10));
}
// 退出方法
public void teardown() {
// 退出浏览器
if (driver != null) {
driver.quit();
}
}
// 测试方法
public void testGetCeshiren() {
// 进入 测试人 社区
driver.get("https://www.ceshiren.com");
// 查找并点击 “类别”
WebElement categoriesButton = driver.findElement(By.cssSelector(".categories"));
categoriesButton.click();
// 获取类别下的文本值
WebElement firstCategory = driver.findElements(By.cssSelector(".category-name")).get(0);
String text = firstCategory.getText();
// 断言
assertEquals("提问区", text, "Expected '提问区' but got: " + text);
}
这个是Java的实现方式,同样都是找到元素然后获取元素文本,最后通过JUnit的断言方法进行断言,更加语义化,测试报告也会更加具有可读性。
总结
精通 CSS 定位技巧对于 Web 自动化测试至关重要,因为使用 CSS 定位能够获取绝大部分元素。这种技能能够提高测试脚本的稳定性和灵活性,有效地支持自动化测试框架中的元素定位操作
最后让我们来总结一下,CSS 定位技巧在 Web 自动化测试中绝对是必备的基础技能。掌握这些技巧,可以帮助我们准确高效地定位页面上的绝大部分元素。这不仅能提升测试脚本的稳定性和灵活性,还为自动化测试框架的开发和维护打下了坚实的基础。所以,熟练应用 CSS 定位,不仅是提升效率的关键,也是让测试更加稳定可靠的有力保障。那么大家一定要多加练习,争取早日熟练使用css定位。