wap手机网站建站,金华公司做网站,网站版权符号代码,花溪村镇建设银行网站UI自动化测试的本质就是将手工测试的一系列动作转化成机器自动执行#xff0c;可以简单概括为五大步骤#xff1a;定位元素 - 操作元素 - 模拟页面动作 - 断言结果 - 生成报告。
所以很多同学在学习时#xff0c;都是以元素定位作为入门导向#xff0c;好的开始就是成功的…
UI自动化测试的本质就是将手工测试的一系列动作转化成机器自动执行可以简单概括为五大步骤定位元素 - 操作元素 - 模拟页面动作 - 断言结果 - 生成报告。
所以很多同学在学习时都是以元素定位作为入门导向好的开始就是成功的一半。
因此本篇将详细介绍Selenium八大元素定位方法以及在自动化测试框架中如何对元素定位方法进行二次封装最后会给出一些在定位元素时的经验总结。 注意本文出现的代码示例均以 Python3.10 Selenium4.5.0 为准由于网上大多数教程都是Selenium3Selenium4相比于Selenium3会有一些新的语法如果你还不了解Selenium4推荐先阅读往期文章「Selenium 4 有哪些不一样」。
Selenium 4 有哪些不一样 | 测试蔡坨坨 Selenium八大元素定位
所谓八大元素定位方式就是id、name、class_name、tag_name、link_text、partial_link_text、xpath、css_selector。 在介绍定位方式之前先来说一下定位工具以Chrome浏览器为例使用F12或右键检查进入开发者工具。
ID
通过元素的id属性定位一般情况下id在当前页面中是唯一的。使用id选择器的前提条件是元素必须要有id属性。由于id值一般是唯一的因此当元素存在id属性值时优先使用id方式定位元素。 例如下面的这个input标签的id属性值为kw
input typetext classs_ipt namewd idkw maxlength100 autocompleteoff 语法 driver.find_element(By.ID, id属性值) 举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(https://www.baidu.com) driver.find_element(By.ID, kw).send_keys(测试) driver.find_element(By.ID, su).click() time.sleep(3) driver.quit()
NAME
通过元素的name属性来定位。name定位方式使用的前提条件是元素必须有name属性。由于元素的name属性值可能存在重复所以必须确定其能够代表目标元素唯一性后方可使用。 当页面内有多个元素的特征值相同时定位元素的方法执行时只会默认获取第一个符合要求的特征对应的元素。 例如下面的这个input标签的name属性值为wd input typetext classs_ipt namewd idkw maxlength100 autocompleteoff 语法 driver.find_element(By.NAME, name属性值)
举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(https://www.baidu.com) driver.find_element(By.NAME, wd).send_keys(测试) driver.find_element(By.ID, su).click() time.sleep(3) driver.quit()
CLASS_NAME
通过元素的class属性来定位class属性一般为多个值。使用class定位方式的前提条件是元素必须要有class属性。 虽然方法名是class_name但是我们要找的是class属性。 例如下面这个input标签的class属性值为but1 input classbut1 typetext namekey placeholder请输入你要查找的关键字 value 语法 driver.find_element(By.CLASS_NAME, class属性值)
举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() # 打开电商网站 driver.get(http://127.0.0.1) driver.maximize_window()
# 搜索框中输入 鞋子 driver.find_element(By.CLASS_NAME, but1).send_keys(鞋子) # 点击搜索 driver.find_element(By.CLASS_NAME, but2).click() 注意如果class name是一个复合类存在多个属性值每个属性值以空格隔开则只能使用其中的任意一个属性值进行定位但是不建议这么做因为可能会定位到多个元素。
例如下面这个标签的class属性值为bg s_btn btn_h btnhover
input classbg s_btn btn_h btnhover typetext namekey 则只能使用复合类的任意一个单词去定位
driver.find_element(By.CLASS_NAME,bg) # 正确示范
driver.find_element(By.CLASS_NAME,bg s_btn btn_h btnhover) # 错误示范 NoSuchElementException
TAG_NAME
通过元素的标签名称来定位例如input标签、button标签、a标签等。 由于存在大量标签并且重复性高因此必须确定其能够代表目标元素唯一性后方可使用。如果页面中存在多个相同标签默认返回第一个标签元素。一般情况下标签重复性过高要精确定位都不会选择tag_name定位方式。 语法 driver.find_element(By.TAG_NAME, 标签名称)
举例 driver.find_element(By.TAG_NAME, input)
LINK_TEXT
定位超链接标签。只能使用精准匹配即a标签的全部文本内容该方法只针对超链接元素a 标签并且需要输入超链接的全部文本信息。 例如下面这个a标签的全部文本内容为联系客服 a hrefhttp://XXX联系客服/a 语法 driver.find_element(By.LINK_TEXT, a标签的全部文本内容)
举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(http://127.0.0.1) driver.maximize_window()
# 点击联系客服 driver.find_element(By.LINK_TEXT, 联系客服).click()
PARTIAL_LINK_TEXT
定位超链接标签与LINK_TEXT不同的是它可以使用精准或模糊匹配也就是a标签的部分文本内容如果使用模糊匹配最好使用能代表唯一的关键词如果有多个元素默认返回第一个。 例如下面这个a标签的全部文本内容为“联系客服”模糊匹配就可以使用a标签的部分文本内容比如联系、客服、联、服…… a hrefhttp://XXX联系客服/a 语法 driver.find_element(By.PARTIAL_LINK_TEXT, a标签的部分文本内容)
举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(http://127.0.0.1) driver.maximize_window() # 点击联系客服 driver.find_element(By.PARTIAL_LINK_TEXT, 联系).click()
XPATH
定义 XML Path Language 的简称用于解析XML和HTML。不仅可以解析XML还可以解析HTML因为HTML与XML是非常相像的XML多用于传输和存储数据侧重于数据HTML多用于显示数据并关注数据的外观 Xpath策略有多种无论使用哪一种策略定位的方法都是同一个不同策略只决定方法的参数的写法。 Xpath不仅可以用于Selenium还适用于Appium是一个万能的定位方式。 Xpath有一个缺点就是速度比较慢比CSS_SELECT要慢很多因为Xpath是从头到尾一点一点去遍历。
绝对路径
从最外层元素到指定元素之间所有经过元素层级的路径 绝对路径是以/html根节点开始使用 / 来分割元素层级的语法比如/html/body/div[2]/div/div[2]/div[1]/form/input[1]因为会有多个div标签所以用索引的方式定位div[2]且XPath的下标是从1开始的例如/bookstore/bool[1]表示选取属于bookstore子元素的第一个book元素除了用数字索引外还可以用last()、position()函数来表达索引例如/bookstore/book[last()]表示选取属于bookstore子元素的最后一个book元素/bookstore/book[last()-1]表示选取属于bookstore子元素的倒数第二个book元素/bookstore/book[position()❤️]表示选取最前面的两个属于bookstore元素的子元素的book元素 由于绝对路径对页面结构要求比较严格因此不建议使用绝对路径。 语法 driver.find_element(By.XPATH, /html开头的绝对路径)
举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() # 打开电商网站 driver.get(http://127.0.0.1) driver.maximize_window()
# 绝对路径 # 搜索框输入 阿迪达斯 # XPath的下标是从1开始的 driver.find_element(By.XPATH, /html/body/div[2]/div/div[2]/div[1]/form/input[1]).send_keys(阿迪达斯) # 点击搜索 driver.find_element(By.XPATH, /html/body/div[2]/div/div[2]/div[1]/form/input[2]).click()driver.quit()
相对路径
匹配任意层级的元素不限制元素的位置 相对路径是以 // 开始 // 后面跟元素名称不知元素名称时可以使用 * 号代替在实际应用中推荐使用相对路径。 语法 driver.find_element(By.XPATH, //input) driver.find_element(By.XPATH, //*)
举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() # 打开电商网站 driver.get(http://127.0.0.1) driver.maximize_window()
# 相对路径 # XPath相对路径以 // 开头 # 搜索框输入 鞋子 driver.find_element(By.XPATH, //input[classbut1]).send_keys(鞋子) # 点击搜索按钮 driver.find_element(By.XPATH, //*[classbut2]).click() 使用浏览器开发者工具直接复制xpath路径值偷懒的方法不推荐在学习的时候使用
通过元素属性定位
单个属性 使用目标元素的任意一个属性和属性值需保证唯一性。 注意 使用 XPath 策略建议先在浏览器开发者工具中根据策略语法组装策略值测试验证后再放入代码中使用。 目标元素的有些属性和属性值可能存在多个相同特征的元素需注意唯一性。
语法 driver.find_element(By.XPATH, //标签名[属性属性值]) driver.find_element(By.XPATH, //*[属性属性值]) 比如下面这个input标签的placeholder属性的属性值为“请输入你要查找的关键字” input classbut1 typetext namekey placeholder请输入你要查找的关键字
举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(http://127.0.0.1) driver.maximize_window()
# 通过单个属性匹配 driver.find_element(By.XPATH, //input[placeholder请输入你要查找的关键字]).send_keys(测试)
多个属性 通过多个属性和属性值进行匹配解决单个属性和属性值无法定位元素唯一性的问题。 多个属性可由多个 and 连接每一个属性都要以 开头可以根据需求使用更多属性值。 语法 driver.find_element(By.XPATH, //标签名[属性1属性值1 and 属性2属性值2]) driver.find_element(By.XPATH, //*[属性1属性值1 and 属性2属性值2]) 比如下面这个input标签的class属性的属性值为but1placeholder属性的属性值为请输入你要查找的关键字 input classbut1 typetext namekey placeholder请输入你要查找的关键字 value
举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(http://127.0.0.1) driver.maximize_window()
# 通过多个属性匹配 driver.find_element(By.XPATH, //input[classbut1 and placeholder请输入你要查找的关键字]).send_keys(测试)
通过属性模糊匹配
通过属性值的部分内容进行匹配。 语法 driver.find_element(By.XPATH, //标签名[contains(属性,属性值的部分内容)]) driver.find_element(By.XPATH, //*[contains(属性,属性值的部分内容)]) 比如下面这个input标签的placeholder属性的属性值为请输入你要查找的关键字模糊匹配就可以是请输入 input classbut1 typetext namekey placeholder请输入你要查找的关键字
举例
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(http://127.0.0.1) driver.maximize_window()
# 通过contains模糊匹配属性值 driver.find_element(By.XPATH, //input[contains(placeholder,请输入)]).send_keys(测试)
starts-with属性值以XX开头 语法 driver.find_element(By.XPATH, //标签名[starts-with(属性,属性值的开头部分)]) driver.find_element(By.XPATH, //*[starts-with(属性,属性值的开头部分)]) 比如下面这个input标签的placeholder属性的属性值以请输入开头 input classbut1 typetext namekey placeholder请输入你要查找的关键字
举例
# function: starts-with定位属性值以xxx开头的元素 from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(http://127.0.0.1) driver.maximize_window()
driver.find_element(By.XPATH, //input[starts-with(placeholder,请输入)]).send_keys(测试)
文本值定位
通过标签的文本值进行定位定位文本值等于XX的元素一般适用于p标签、a标签。 语法 driver.find_element(By.XPATH, //*[text()文本信息]) 比如下面这个a标签的文本信息为免费注册 a hrefhttp://127.0.0.1/register免费注册/a
举例
# function: text()文本信息定位 from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(http://127.0.0.1) driver.maximize_window()
driver.find_element(By.XPATH, //*[text()免费注册]).click()
CSS_SELECTOR
通过CSS选择器语法定位元素。 适用于Selenium和Appium但是需要注意的是原生的app控件不支持CSS_SELECTOR只支持Xpath。 Selenium框架官方推荐使用CSS定位因为CSS定位效率高于XPATH。 CSS是一种标记语言控制元素的显示样式就必须找到元素在CSS标记语言中找元素使用CSS选择器。 CSS的选择策略也多很多种但是无论选择哪一种选择策略都是用同一种定位方法。 定位方法 driver.find_element(By.CSS_SELECTOR, CSS选择策略)
绝对路径
以html开始使用 或 空格 分隔与XPATH一样CSS_SELECTOR的下标也是从1开始。 driver.find_element(By.CSS_SELECTOR, htmlbodydivdivdivdivforminput:nth-child(1)).send_keys(测试) # 使用分隔 driver.find_element(By.CSS_SELECTOR, html body div div div div form input:nth-child(1)).send_keys(测试) # 使用空格分隔 driver.find_element(By.CSS_SELECTOR, htmlbodydivdiv div div form input:nth-child(1)).send_keys(测试) # 使用 空格 分隔
相对路径
不以html开头以CSS选择器开头比如标id选择器、class选择器等。 举例 driver.find_element(By.CSS_SELECTOR, input.but1).send_keys(测试)
id选择器
语法# 开头表示id选择器 driver.find_element(By.CSS_SELECTOR, 标签#id属性值) 举例 driver.find_element(By.CSS_SELECTOR, i#cart_num).click()
class选择器
语法. 开头表示class选择器或者使用[classclass属性值] 如果具有多个属性值的class则需要传入全部的属性值 driver.find_element(By.CSS_SELECTOR, .class属性值) driver.find_element(By.CSS_SELECTOR, [classclass属性值])
举例 driver.find_element(By.CSS_SELECTOR, .but2).click() driver.find_element(By.CSS_SELECTOR, [classbut2]).click()
属性选择器
单个属性
语法 driver.find_element(By.CSS_SELECTOR, 标签名[属性属性值]) driver.find_element(By.CSS_SELECTOR, [属性属性值]) 举例 driver.find_element(By.CSS_SELECTOR, input[placeholder请输入你要查找的关键字]).send_keys(测试) driver.find_element(By.CSS_SELECTOR, [placeholder请输入你要查找的关键字]).send_keys(测试)
多个属性
语法注意与xpath的区别 driver.find_element(By.CSS_SELECTOR, 标签名[属性1属性值1][属性2属性值2]) 举例 driver.find_element(By.CSS_SELECTOR, input[namekey][classbut1]).send_keys(测试)
模糊匹配
driver.find_element(By.CSS_SELECTOR, [属性^开头的字母]) # 获取指定属性以指定字母开头的元素 driver.find_element(By.CSS_SELECTOR, [属性$结束的字母]) # 获取指定属性以指定字母结束的元素 driver.find_element(By.CSS_SELECTOR, [属性*包含的字母]) # 获取指定属性包含指定字母的元素
标签选择器 语法 driver.find_element(By.CSS_SELECTOR, 标签名) # 例如input、button 层级关系 父子层级关系父层级策略 子层级策略 也可以使用空格连接上下层级 祖辈后代层级关系祖辈策略 后代策略 与 空格 的区别大于号必须为子元素空格则不用
first-child
第一个子元素
div classhelp a hrefhttp://127.0.0.1首页/a a hrefhttp://127.0.0.1/buy我的订单/a a hrefhttp://127.0.0.1//help联系客服/a /div driver.find_element(By.CSS_SELECTOR, .helpa:first-child).click() # 首页
last-child 最后一个子元素
driver.find_element(By.CSS_SELECTOR, .helpa:last-child).click() # 联系客服 nth-last-child()
倒序 driver.find_element(By.CSS_SELECTOR, .helpa:nth-last-child(2)).click() # 我的订单nth-child()
正序 driver.find_element(By.CSS_SELECTOR, .helpa:nth-child(3)).click() # 联系客服
干儿子和亲儿子 若一个标签下有多个同级标签虽然这些同级标签的 tag name 不一样但是他们是放在一起排序的。
# function: css_selector 不区分干儿子和亲儿子
import time from selenium import webdriver from selenium.webdriver.common.by import By
driver webdriver.Chrome() driver.get(https://www.baidu.com) driver.maximize_window()
# css_selector 不区分干儿子和亲儿子 # 若一个标签下有多个同级标签虽然这些同级标签的tag name不一样但是他们是放在一起排序的 # 打开百度在搜索框中输入 测试 点击百度一下 driver.find_element(By.CSS_SELECTOR, form#formspan:nth-child(8)input).send_keys(测试) driver.find_element(By.CSS_SELECTOR, form#formspan:nth-child(9)input).click() 元素定位二次封装 在之前的文章中我们介绍过UI自动化测试框架可参考往期文章「五分钟搞懂 POM 设计模式」 https://www.caituotuo.top/ec719945.html 框架中的base_page模块对Selenium一些常用的API进行二次封装其中就有对find_element的封装。
base_page.py
class BasePage(object): def __init__(self, driver): self.logger GetLogger().get_logger() self.driver driver def wait_ele_visible_(self, loc, loc_doc, times3, poll_frequency0.5): 等待元素可见 :param loc: 元素定位 :param loc_doc: 元素描述 :param times: 最长等待时间 :param poll_frequency: 轮询频率调用 until 或 until_not方法中的间隔时间默认为0.5秒 :return: try: do_time def fun(): WebDriverWait(self.driver, times, poll_frequency).until(EC.visibility_of_element_located(loc)) self.logger.info(等待【{}】元素【{}】出现耗时{}豪秒.format(loc_doc, loc, fun())) except Exception: self.logger.error(等待【{}】元素【{}】出现失败.format(loc_doc, loc)) raise def find_element_(self, loc, loc_doc): 查找元素 :param loc: 元素定位 例如login_icon_loc (By.ID, sb_form_q) :param loc_doc: 对元素的描述 :return: try: self.logger.info(开始查找【{}】元素【{}】.format(loc_doc, loc)) self.wait_ele_visible_(loc, loc_doc) return self.driver.find_element(*loc) except Exception: self.logger.error(查找【{}】元素【{}】失败.format(loc_doc, loc)) raise
元素定位总结
首先考虑id定位id定位是效率最高的 一般情况下id属性在当前页面是唯一的。 在实际企业项目中可能需要前端同学的配合保证元素唯一属性命名规则。所有可操作元素例如输入框、点击按钮等均需要加id字段并且id字段的命名为元素含义的英文若当前页面存在两个或多个一样的元素则第二个开始命名为idusername2以此类推多层级元素一般最外层定义即可。如果没有id再选择xpath一般使用相对路径
css_selector比xpath更加稳定 为什么说css_selector比xpath更稳定因为我们通过Chrome浏览器的开发者工具可以看出蓝色线代表DOM出现红色线代表图片等资源已加载完如果用xpath定位元素其实是在DOM出现的时候进行查找而当你使用css_selector进行元素定位的时候它会等待图片资源加载完成后进行查找也就是红线的位置所以css_selector比xpath更稳定当你使用xpath定位不到元素时不妨尝试使用css_selector。
tag_name使用频率最低 尽量不要用href属性、纯数字的属性纯数字可能是个动态值去定位 对于Toast提示框很快消失的提示框可以点击 开发者工具-sources中的暂停键 后再去定位
添加适当的等待时间避免等待时间不够元素还未加载出来 多窗口时需考虑窗口句柄是否还处在上一个窗口导致无法定位新窗口的元素是否需要切换窗口句柄 iframe/frame这是个常见的定位不到元素的原因frame中实际上是嵌入了另一个页面而webdriver每次只能在一个页面识别因此需要先定位到相应的frame再对那个页面里的元素进行定位 如果使用xpath或css_selector请在浏览器开发者工具中调试测试正确后再写入代码中
Web UI 自动化测试框架https://github.com/itcaituotuo/ui_auto_test_framework 接口自动化测试框架https://github.com/itcaituotuo/api_auto_test_framework PythonToolshttps://github.com/itcaituotuo/PythonTools