龙空技术网

软件测试/测试开发丨用户端Web自动化测试学习笔记

霍格沃兹测试开发学社 66

前言:

今天朋友们对“jquery寻找邻近节点”大约比较关切,看官们都想要剖析一些“jquery寻找邻近节点”的相关知识。那么小编在网络上网罗了一些对于“jquery寻找邻近节点””的相关文章,希望朋友们能喜欢,你们一起来了解一下吧!

点此获取更多相关资料>「链接」

本文为霍格沃兹测试开发学社学员学习笔记分享

原文链接:用户端web自动化测试-l1~l2--Loxida - 学习笔记 - 测试人社区

一、SeleniumIDE用例录制1、SeleniumIDE的下载以及安装官网:插件:Firefox插件:github release:其它版本:注意:Chrome插件在国内无法下载,Firefox可以直接下载。2、启动安装完成后,通过在浏览器的菜单栏中点击它的图标来启动它:如果没看到图标,首先确保是否安装了Selenium IDE扩展插件通过以下链接访问所有插件Chrome: chrome://extensionsFirefox: about:addons3、SeleniumIDE常用功能新建、保存、打开开始和停止录制运行8中的所有的实例运行单个实例调试模式调整案例的运行速度要录制的网址实例列表动作、目标、值对单条命令的解释运行日志4、SeleniumIDE脚本导出:Java和Python二、自动化测试用例结构分析1、标准的用例结构(功能)用例标题前提条件用例步骤预期结果实际结果2、自动化用例结构及作用

【结构:自动化测试用例:作用】

用例标题:测试包、文件、类、方法名称:【用例的唯一标识】前提条件:setup、setup_class(Pytest;BeforeEach、BeforeAll(JUnit):【测试用例前的准备动作,比如读取数据或者driver的初始化】用例步骤:测试方法内的代码逻辑:【测试用例具体的步骤行为】预期结果:assert 实际结果 = 预期结果:【断言,印证用例是否执行成功】实际结果:assert 实际结果 = 预期结果:【断言,印证用例是否执行成功】后置动作:teardown、teardown_class(Pytest);@AfterEach、@AfterAll(JUnit):【脏数据清理、关闭driver进程】3、IDE录制脚本脚本步骤:访问百度网站搜索框输入“霍格沃兹测试开发”点击搜索按钮

# Generated by Selenium IDEimport pytestimport timeimport jsonfrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsfrom selenium.webdriver.support import expected_conditionsfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesclass Test():  def setup_method(self, method):    self.driver = webdriver.Chrome()    self.vars = {}    def teardown_method(self, method):    self.driver.quit()    def test_sougou(self):    # 打开网页,设置窗口    self.driver.get(";)    self.driver.set_window_size(1235, 693)    # 输入搜索信息    self.driver.find_element(By.ID, "query").click()    self.driver.find_element(By.ID, "query").send_keys("霍格沃兹测试开发")    # 点击搜索    self.driver.find_element(By.ID, "stb").click()    element = self.driver.find_element(By.ID, "stb")    actions = ActionChains(self.driver)    actions.move_to_element(element).perform()
#优化后的代码,添加断言判断用例是否成功# Generated by Selenium IDEimport pytestimport timeimport jsonfrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsfrom selenium.webdriver.support import expected_conditionsfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesclass Test(object):    # 前提条件,webdriver的初始化    def setup_method(self, method):        self.driver = webdriver.Chrome()        self.vars = {}    # 后置操作,关闭网站    def teardown_method(self, method):        self.driver.quit()    # 测试用例步骤    def test_sougou(self):        # 打开网页,设置窗口        self.driver.get(";)        self.driver.set_window_size(1235, 693)        # 输入搜索信息        self.driver.find_element(By.ID, "query").click()        self.driver.find_element(By.ID, "query").send_keys("霍格沃兹测试开发")        # 点击搜索        self.driver.find_element(By.ID, "stb").click()        element = self.driver.find_element(By.ID, "stb")        actions = ActionChains(self.driver)        actions.move_to_element(element).perform()        # 问题:无法确定用例执行成功或失败        # 解决方案:添加断言信息,判断搜索列表中,是否会有"霍格沃兹测试开发"        res_element = self.driver.find_element(By.CSS_SELECTOR, "#sogou_vr_30000000_0 > em")        # 获取到定位的文本信息        # 判断实际获取到的搜索展示的列表和预期是否一致        assert res_element.text == "霍格沃兹测试开发"
三、web 浏览器控制模拟功能测试中对浏览器的操作

操作

使用场景

get

打开浏览器

web自动化测试第一步

refresh

浏览器刷新

模拟浏览器刷新

back

浏览器退回

模拟退回步骤

maximize_window

最大化浏览器

模拟浏览器最大化

minimize_window

最小化浏览器

模拟浏览器最小化

import timefrom selenium import webdriver# 打开网页def open_browser():    # 实例化chromedriver    driver = webdriver.Chrome()    # 调用get方法时需要传递浏览器的URL    driver.get(";)    # 添加等待1秒    time.sleep(2)    # # 刷新浏览器    # driver.refresh()    # # 通过get跳转到百度    # driver.get(";)    # # 回退操作,退回到测试人网页    # driver.back()    # 最大化浏览器    driver.maximize_window()    time.sleep(2)    # 最小化浏览器    driver.minimize_window()    time.sleep(2)if __name__ == '__main__':    open_browser()
四、常见控件定位方法1、HTML铺垫标签:尖括号,如括起来的<a>、<html>、<title>等属性:a=b,如href类属性: class
<!DOCTYPE html><html><head><meta charset="utf-8"><title>测试人论坛</title></head><body><a href="; class="link">链接</a></body></html>
2、Selenium八大定位方式selenium 常用定位方式格式:

driver.find_element_by_定位方式(定位元素)

driver.find_element(By.定位方式, 定位元素)

示例,两种方式作用一模一样官方建议使用下面的方式

driver.find_element_by_id("su")

driver.find_element(By.ID, "su")

方式

描述

class name

class 属性对应的值

css selector(重点)

css 表达式

id(重点)

id 属性对应的值

name(重点)

name 属性对应的值

link text

查找其可见文本与搜索值匹配的锚元素

partial link text

查找其可见文本包含搜索值的锚元素。如果多个元素匹配,则只会选择第一个元素。

tag name

标签名称

xpath(重点)

xpath表达式

【方式:描述】class name:class 属性对应的值css selector(重点):css 表达式 格式: driver.find_element(By.CSS_SELECTOR, "css表达式") 复制绝对定位 编写 css selector 表达式id(重点):id 属性对应的值 格式: driver.find_element(By.ID, "ID属性对应的值")name(重点):name 属性对应的值 格式: driver.find_element(By.NAME, "Name属性对应的值")link text:查找其可见文本与搜索值匹配的锚元素 格式:driver.find_element(By.LINK_TEXT,"文本信息")partial link text:查找其可见文本包含搜索值的锚元素。如果多个元素匹配,则只会选择第一个元素。tag name:标签名称xpath(重点):xpath表达式 格式: driver.find_element(By.XPATH, "xpath表达式") 复制绝对定位 编写 xpath 表达式

from selenium import webdriverfrom selenium.webdriver.common.by import Bydef web_locate():    # 首先需要实例化driver对象,Chrome一定要加括号    driver = webdriver.Chrome()    # 打开一个网页    driver.get(";)    # 1.ID定位,第一个参数传递定位方式,第二个参数传递定位元素,调用这个方法的返回值为WebElement    web_element = driver.find_element(By.ID, "locate_id")    print(web_element)    # 2.NAME定位,如果没有报错,证明元素找到了    # 如果报错no such element,代表元素定位可能出现错误    # driver.find_element(By.NAME, "locate123")   # 错误示例    driver.find_element(By.NAME, "locate")    # 3.CSS选择器定位    driver.find_element(By.CSS_SELECTOR, "#locate_id > a > span")    # 4.xpath表达式定位    driver.find_element(By.XPATH, '//*[@id="locate_id"]/a/span')  # 表达式里有双引号,建议用单引号    # 5.Link text,通过链接文本的方式,(1)元素一定是a标签;(2)输入的元素为标签内的文本    driver.find_element(By.LINK_TEXT, "元素定位")   # 通常会带一个点击的操作,在最后面添加.click(),可加可不加if __name__ == '__main__':    web_locate()
五、强制等待与隐式等待1、为什么要添加等待

避免页面未渲染完成后操作,导致的报错

from selenium import webdriverfrom selenium.webdriver.common.by import Bydef wait_sleep():    """    如果直接执行,不添加任何等待,可能会报错    """    driver = webdriver.Chrome()    driver.get(";)    # 不加等待,可能会因为网速等原因产生报错    # 报错:no such element: Unable to locate element    # 原因:页面未加载完成,就去查找元素,此时这个元素还未加载出来    driver.find_element(By.XPATH, "//*[text()='个人中心']")if __name__ == '__main__':    wait_sleep()
2、强制(直接)等待解决方案:在报错的元素操作之前添加等待原理:强制等待,线程休眠一定时间。time.sleep(3)
import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditionsfrom selenium.webdriver.support.wait import WebDriverWaitdef wait_sleep():    """    如果直接执行,不添加任何等待,可能会报错    """    driver = webdriver.Chrome()    driver.get(";)    # 不加等待,可能会因为网速等原因产生报错    # 报错:no such element: Unable to locate element    # 原因:页面未加载完成,就去查找元素,此时这个元素还未加载出来    # 1.强制等待,让页面渲染完成,在报错的元素操作之前添加等待,没有报错,就证明是页面渲染速度导致,有报错则是其他问题,如定位错误等    time.sleep(3)    driver.find_element(By.XPATH, "//*[text()='个人中心']")if __name__ == '__main__':    wait_sleep()
3、隐式等待问题:难以确定元素加载的具体等待时间。解决方案:针对于寻找元素的这个动作,使用隐式等待添加配置。原理:设置一个等待时间,轮询查找(默认0.5秒)元素是否出现,如果没出现就抛出异常
import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditionsfrom selenium.webdriver.support.wait import WebDriverWaitdef wait_sleep():    """    如果直接执行,不添加任何等待,可能会报错    """    driver = webdriver.Chrome()    driver.get(";)    # 不加等待,可能会因为网速等原因产生报错    # 报错:no such element: Unable to locate element    # 原因:页面未加载完成,就去查找元素,此时这个元素还未加载出来    # 1.强制等待,让页面渲染完成,在报错的元素操作之前添加等待,没有报错,就证明是页面渲染速度导致,有报错则是其他问题,如定位错误等    # time.sleep(3)    # 强制等待的问题:(1)不确定页面加载时间,可能会因为等待时间过长,而影响用例的执行效率;(2)不确定页面加载时间,可能会因为等待时间过短,而导致代码依然报错    # 2.隐式等待    # 设置一个最长的等待时间,轮询查找(默认0.5秒)元素是否出现,如果没出现就抛出异常    # 注意:(1)在代码一开始运行时就添加隐式等待的配置,隐式等待是全局生效,即在所有find_element动作之前添加该配置即可;(2)隐式等待只能解决元素查找问题,不能解决元素交互问题    driver.implicitly_wait(3)    driver.find_element(By.XPATH, "//*[text()='个人中心']")    # driver.implicitly_wait(5)    # 修改隐式等待的配置    driver.find_element(By.XPATH, "//*[text()='题库']")
4、隐式等待无法解决的问题问题:元素可以找到,使用点击等操作,出现报错原因:页面元素加载是异步加载过程,通常html会先加载完成,js、css其后元素存在与否是由HTML决定,元素的交互是由css或者js决定隐式等待只关注元素能不能找到,不关注元素能否点击或者进行其他的交互解决方案:使用显式等待5、显式等待基本使用(初级)示例: WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件)原理:在最长等待时间内,轮询,是否满足结束条件在初级时期,先关注使用
import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditionsfrom selenium.webdriver.support.wait import WebDriverWait"""显示等待"""def wait_show():    driver = webdriver.Chrome()    driver.get(";)    # driver.implicitly_wait(3)  # 问题:元素可以找到,但是点击效果没有触发    # 显示等待,第一个参数是driver,第二个参数是最长等待时间,轮询时间可加可不加,util方法内需要结合expected_conditions或者自己封装的方法进行使用    # expected_conditions的参数传入都是一个元组,即多一层小括号    WebDriverWait(driver, 10).until(expected_conditions.element_to_be_clickable((By.ID, "success_btn")))    driver.find_element(By.ID, "success_btn").click()   # 添加点击操作.click(),点击"消息提示"    time.sleep(5)if __name__ == '__main__':    wait_show()
6、总结直接等待:使用方式:time.sleep(等待时间))原理:强制线程等待适用场景:调试代码,临时性添加隐式等待:使用方式:driver.implicitly_wait(等待时间)原理:在时间范围内,轮询查找元素适用场景:解决找不到元素问题,无法解决交互问题显式等待:使用方式:WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件)原理:设定特定的等待条件,轮询操作适用场景:解决特定条件下的等待问题,比如点击等交互性行为六、常见控件交互方法1、元素操作

点击,输入,清空

import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Bydef element_interaction():    """    元素操作:点击、输入、清空    :return:    """    # 1.实例化driver对象    driver = webdriver.Chrome()    # 2.打开一个网页    driver.get(";)    # 3.定位到输入框进行输入操作,.send_keys()    driver.find_element(By.ID, "query").send_keys("霍格沃滋测试开发")    # 强制等待2秒    time.sleep(2)    # 4.对输入框进行清空操作.clear()    driver.find_element(By.ID, "query").clear()    time.sleep(2)    # 5.再次输入    driver.find_element(By.ID, "query").send_keys("霍格沃滋测试开发学社")    time.sleep(2)    # 6.点击搜索.click()    driver.find_element(By.ID, "stb").click()    time.sleep(2)if __name__ == '__main__':    element_interaction()
2、获取元素属性信息原因:定位到元素后,获取元素的文本信息,属性信息等目的:根据这些信息进行断言或者调试
import timefrom selenium import webdriverfrom selenium.webdriver.common.by import By# 获取元素属性def element_get_attr():    # 1.实例化driver对象    driver = webdriver.Chrome()    # 2.打开网页    driver.get(";)    # 3.定位一个元素    web_element = driver.find_element(By.ID, "locate_id")    # 4.打印这个元素信息    # 使用debug方式查看,断点打在想看的对象的下一行    # print(web_element)    # 5.获取元素的文本信息,不是每个元素都有文本信息的    print(web_element.text)    # 6.获取元素的属性信息,如 id="locate_id", title="xxx"    res = web_element.get_attribute("class")    print(res)if __name__ == '__main__':    # 获取元素属性    element_get_attr()
3、获取元素属性信息的方法获取元素文本获取元素的属性(html的属性值)
# 获取元素文本driver.find_element(By.ID, "id").text# 获取这个元素的name属性的值driver.find_element(By.ID, "id").get_attribute("name")
七、自动化测试定位策略1、定位方式2、通用 Web 定位方式

定位策略

描述

class name

通过 class 属性定位元素

css selector

通过匹配 css selector 定位元素

id

通过 id 属性匹配元素

name

通过 name 属性定位元素

link text

通过 text 标签中间的 text 文本定位元素

partial link text

通过 text 标签中间的 text 文本的部分内容定位元素

tag name

通过 tag 名称定位元素

xpath

通过 xpath 表达式匹配元素

3、选择定位器通用原则与研发约定的属性优先(class属性: [name='locate'])身份属性 id,name(web 定位)复杂场景使用组合定位:xpath,css属性动态变化(id,text)重复元素属性(id,text,class)父子定位(子定位父)js定位4、Web 弹框定位场景:web 页面 alert 弹框解决:web 需要使用 driver.switchTo().alert() 处理5、下拉框/日期控件定位场景:<input>标签组合的下拉框无法定位<input>标签组合的日期控件无法定位解决:面对这些元素,我们可以引入JS注入技术来解决问题。6、文件上传定位场景:input 标签文件上传解决:input 标签直接使用 send_keys()方法L1实战–测试人论坛搜索功能自动化测试

from selenium import webdriverfrom selenium.webdriver.common.by import Byclass TestCeshiren01:    def setup(self):        """        前提条件:进入测试人论坛的搜索页面        :return:        """        # 实例化driver对象        self.driver = webdriver.Chrome()        self.driver.implicitly_wait(3)  # 隐式等待        # 打开被测地址        self.driver.get(";)    def teardown(self):        # 每一次用例结束之后都会关闭chromedriver进程,也会关闭浏览器        self.driver.quit()    def test_search01(self):        """        测试步骤:1.输入搜索关键词;2.点击搜索按钮        :return:        """        # 定位搜索框,并输入搜索内容,如果是动态id,使用css        self.driver.find_element(By.CSS_SELECTOR, "[placeholder=搜索]").send_keys("appium")        # 定位到搜索按钮,并点击搜索        self.driver.find_element(By.CSS_SELECTOR, ".search-cta").click()        # 断言=预期结果与实际结果对比的结果        # 定位实际结果,即为获取搜索结果列表的标题内容        web_element = self.driver.find_element(By.CSS_SELECTOR, ".topic-title")        # 获取文本类的实际结果断言,appium关键字是否在获取的实际结果文本之中        assert "appium" in web_element.text
八、高级定位-css1、css 选择器概念css 选择器有自己的语法规则和表达式css 定位通常分为绝对定位和相对定位和Xpath一起常用于UI自动化测试中的元素定位2、css 相对定位使用场景支持web产品支持app端的webview3、css 相对定位的优点可维护性更强语法更加简洁解决各种复杂的定位场景4、css 定位的调试方法进入浏览器的console输入:$("css表达式")或者$$("css表达式"),如果表达式里有双引号,外面要单引号,如果表达式用的是单引号,外面就要用双引号,外双内单,外单内双5、css基础语法

类型

表达式

标签

标签名

. (表示class属性值)

ID

# (表示id属性值)

属性

[属性名=‘属性值’]

【类型:表达式】

标签:标签名$("div") 获取所有的div标签类:.表示为class属性值,如果类里面有多个值(单词),就不能直接复制,将空格改为.即可$(".logo-big")等同于$("[class='logo-big']")ID:#表示为id属性值$("#site-logo")等同于$("[id='site-logo']")属性:[属性名='属性值']$("[alt='测试人社区']")6、css关系定位

类型

格式

并集

元素,元素

邻近兄弟(了解即可)

元素+元素

兄弟(了解即可)

元素1~元素2

父子

元素>元素

后代

元素 元素

【类型:格式】

并集:元素,元素$("#main,#ember4")邻近兄弟(了解即可):元素+元素 $("#ember39+#ember40")兄弟(了解即可):元素1~元素2 $("#ember39~#ember41")父子:元素>元素 $("#main>#ember4")后代:元素 元素 $("#main #skip-link")7、css 顺序关系

类型

格式

父子关系+顺序

元素 元素

父子关系+标签类型+顺序

元素 元素

【类型:格式】

父子关系+顺序:元素 元素(父亲有多个孩子,找到第一个孩子) 表达式://:nth-child(n) $("#ember15>:nth-child(3)") ( #ember15为父亲,:nth-child(3)为第三个孩子)父子关系+标签类型+顺序:元素 元素(父亲的孩子有多个类型,想找其中一个类型里面的第一个孩子) 表达式://:nth-of-type(n) $("#ember15>div:nth-of-type(1)")( #ember15为父亲,:nth-of-type(1)为第三个类型div的第一个孩子)

css表达式定位

九、高级定位-xpath1、xpath 基本概念XPath 是一门在 XML 文档中查找信息的语言XPath 使用路径表达式在 XML 文档中进行导航XPath 的应用非常广泛XPath 可以应用在UI自动化测试2、xpath 使用场景web自动化测试app自动化测试3、xpath 相对定位的优点可维护性更强语法更加简洁相比于css可以支持更多的方式4、xpath 定位的调试方法浏览器-console$x("xpath表达式")浏览器-elementsctrl+f 输入xpath或者css5、xpath 基础语法(包含关系)

表达式

结果

/

从该节点的子元素选取

//

从该节点的子孙元素选取

*

通配符

nodename

选取此节点的所有子节点

选取当前节点的父节点

@

选取属性

【表达式:结果】

/ :从该节点的子元素选取// :从该节点的子孙元素选取:通配符 $x("//*[@id='ember61']"),匹配所有的[@id='ember61'] $x("//tr[@id='ember61']"),匹配tr标签下面的[@id='ember61']nodename :选取此节点的所有子节点,相当于标签名.. :选取当前节点的父节点, 如$x("//*[@id='ember61']/.."),寻找ember61的父节点

写法二:$x("//tr[@id='ember61']"),在某个标签下寻找

@ :选取属性整个页面 $x("/")

页面中的所有的子元素,匹配/下面的所有节点,相当于是html $x("/*")

整个页面中的所有元素 $x("//*")

查找页面上面所有的div标签节点,标签不等于属性 $x("//div")

查找id属性为ember61的节点,*先匹配所有节点,再匹配某个属性 $x('//*[@id="ember61"]')

查找ember61节点的父节点

$x('//*[@id="ember61"]/..')

$x("//*[@id='ember61']/../..") 再往上寻找父节点

6、xpath 顺序关系(索引)

xpath通过索引直接获取对应元素# 查找tbody下的所有tr$x("//tbody//tr")# 查找tbody下的第一个tr,下标从1开始$x("//tbody//tr[1]")# 获取所有的tr,注意这里的tr并不是都是同一个父节点$x("//tr")# 获取每个不同父节点下面的第一个tr$x("//tr[1]")
7、xpath 高级用法
①[last()]: 选取最后一个$x("//tr[last()]")   # 获取每一个父节点下的最后一个tr$x("//tbody//tr[last()]")   # 获取tbody下面的最后一个tr②[@属性名='属性值' and @属性名='属性值']: 与关系$x("//*[@class='topic-list-item category-bu-161-category unseen-topic ember-view' and @id='ember44']")③[@属性名='属性值' or @属性名='属性值']: 或关系$x("//*[@class='topic-list-item category-bu-161-category unseen-topic ember-view' or @id='ember44']")④[text()='文本信息']: 根据文本信息定位$x("//*[text()='赏金任务']")   # text不是属性,不需要加@,是一个方法,加括号⑤[contains(text(),'文本信息')]: 根据文本信息包含定位;也可以contains(@id或@name等)$x("//*[contains(text(),'赏金')]")$x("//*[contains(@id,'site')]")⑥注意:所有的表达式需要和[]结合
十、显式等待高级使用1、显式等待原理在代码中定义等待一定条件发生后再进一步执行代码在最长等待时间内循环执行结束条件的函数,结合③一起查看源码:WebDriverWait(driver 实例, 最长等待时间, 轮询时间).until(结束条件函数)2、常见 expected_conditions

类型

示例方法

说明

element

element_to_be_clickable();visibility_of_element_located()

针对于元素,比如判断元素是否可以点击,或者元素是否可见

url

url_contains()

针对于 url

title

title_is()

针对于标题

frame

frame_to_be_available_and_switch_to_it(locator)

针对于 frame

alert

alert_is_present()

针对于弹窗

3、封装等待条件官方的 excepted_conditions 不可能覆盖所有场景,如有些按钮需要点击两次或多次才会有反应定制封装条件会更加灵活、可控

import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.remote.webdriver import WebDriverfrom selenium.webdriver.support.wait import WebDriverWaitclass TestWebdriverWait:    driver = webdriver.Chrome()    driver.maximize_window()    driver.implicitly_wait(5)    driver.get(";)    def teardown(self):        self.driver.quit()    def test_webdriver_wait(self):        # 解决的问题:有的按钮点击一次没有反应,可能要点击多次,比如企业微信的添加成员        # 解决的方案:一直点击按钮,直到下个页面出现,封装成显式等待的一个条件        def muliti_click(button_element,until_ele):            # 函数封装            def inner(driver):                # 封装点击方法                driver.find_element(By.XPATH,button_element).click()                return driver.find_element(By.XPATH,until_ele)            return inner        time.sleep(5)        # 在限制时间内会一直点击按钮,直到展示弹框        WebDriverWait(self.driver,10).until(muliti_click("//*[text()='点击两次响应']","//*[text()='该弹框点击两次后才会弹出']"))        time.sleep(5)
十一、高级控件交互方法1、使用场景

使用场景

对应事件

复制粘贴

键盘事件

拖动元素到某个位置

鼠标事件

鼠标悬停

鼠标事件

滚动到某个元素

滚动事件

使用触控笔点击

触控笔事件(了解即可)

2、ActionChains解析实例化类ActionChains,参数为driver实例。中间可以有多个操作。.perform()代表确定执行。3、键盘事件按下、释放键盘键位结合send_keys回车键盘事件-使用shift实现大写ActionChains(self.driver): 实例化ActionChains类key_down(Keys.SHIFT, ele): 按下shift键实现大写send_keys("selenium"): 输入大写的seleniumperform(): 确认执行

from selenium import webdriverfrom selenium.webdriver import ActionChains, Keysfrom selenium.webdriver.common.by import Byclass TestKeyBoard:    def setup_class(self):        self.driver = webdriver.Chrome()        self.driver.implicitly_wait(3)  # 隐式等待3秒    def teardown_class(self):        self.driver.quit()    def test_shift(self):        """	     键盘事件-使用shift实现大写        1.访问官方网站        2.点击搜索按钮        3.输入搜索的内容,输入的同时按着shift键        :return:        """        self.driver.get(";)        # 点击搜索按钮        self.driver.find_element(By.ID, "search-button").click()        # 目标元素,即为输入框        ele = self.driver.find_element(By.ID, "search-term")        # key_down代表按下某个键位,.send_keys输入内容,.perform()确认执行以上操作        ActionChains(self.driver).key_down(Keys.SHIFT, ele).send_keys("selenium").perform()
键盘事件-输入后回车直接输入回车: 元素.send_keys(Keys.ENTER)使用ActionChains: key_down(Keys.ENTER)
from selenium import webdriverfrom selenium.webdriver import ActionChains, Keysfrom selenium.webdriver.common.by import Byclass TestKeyBoard:    def setup_class(self):        self.driver = webdriver.Chrome()        self.driver.implicitly_wait(3)  # 隐式等待3秒    def teardown_class(self):        self.driver.quit()    def test_enter(self):	 """键盘事件-输入后回车"""        self.driver.get(";)        self.driver.find_element(By.ID, "query").send_keys("python语言")        # 第一种回车方式,直接输入回车        self.driver.find_element(By.ID, "query").send_keys(Keys.ENTER)        # 第二种使用ActionChains,要记得加.perform()        ActionChains(self.driver).key_down(Keys.ENTER).perform()
键盘事件-复制粘贴多系统兼容 mac 的复制按钮为 COMMAND windows 的复制按钮为 CONTROL左箭头:Keys.ARROW_LEFT按下COMMAND或者CONTROL: key_down(cmd_ctrl)按下剪切与粘贴按钮: send_keys("xvvvvv")
import sysfrom selenium import webdriverfrom selenium.webdriver import ActionChains, Keysfrom selenium.webdriver.common.by import Byclass TestKeyBoard:    def setup_class(self):        self.driver = webdriver.Chrome()        self.driver.implicitly_wait(3)  # 隐式等待3秒    def teardown_class(self):        self.driver.quit()    def test_copy_and_paste(self):        """键盘事件-复制粘贴"""        # 打开网页        self.driver.get(";)        # 点击搜索按钮        self.driver.find_element(By.ID, "search-button").click()        # 目标元素,即为输入框        ele = self.driver.find_element(By.ID, "search-term")        # 判断操作系统是否为Mac(darwin),是mac返回command键位,windows返回control键位        command_control = Keys.COMMAND if sys.platform == "darwin" else Keys.CONTROL        # .key_down(Keys.SHIFT, ele)按下shift键,.send_keys("selenium")输入大写selenium,        # .key_down(Keys.ARROW_LEFT)按下左箭头,.key_down(command_control)按下command或control键位,        # .send_keys("xvv"),x表示为剪切,多少个v表示复制多少次,.key_up(command_control)表示松开command或control键位,.perform()执行        ActionChains(self.driver)\            .key_down(Keys.SHIFT, ele)\            .send_keys("selenium@")\            .key_down(Keys.ARROW_LEFT)\            .key_down(command_control).send_keys("xvvvvvv").key_up(command_control)\            .perform()
4、鼠标事件双击 double_click(元素对象): 双击元素拖动元素 drag_and_drop(起始元素对象, 结束元素对象): 拖动并放开元素指定位置(悬浮) move_to_element(元素对象): 移动到某个元素
import timefrom selenium import webdriverfrom selenium.webdriver import ActionChains, Keysfrom selenium.webdriver.common.by import Byclass TestKeyBoard:    def setup_class(self):        self.driver = webdriver.Chrome()        self.driver.implicitly_wait(3)  # 隐式等待3秒    def teardown_class(self):        self.driver.quit()    def test_double_click(self):        """鼠标事件-双击"""        # 打开网页        self.driver.get(";)        # 获取点击按钮        ele = self.driver.find_element(By.ID, "primary_btn")        # .double_click(ele)调用双击方法,传入双击元素,.perform()执行        ActionChains(self.driver).double_click(ele).perform()    def test_drag_and_drop(self):        """鼠标事件-拖动元素"""        # 打开网页        self.driver.get(";)        # 获取需要拖动的元素,即起始元素的位置        item_left = self.driver.find_element(By.CSS_SELECTOR, '#item1')   # #表示id标签        # 获取目标元素的位置        item_right = self.driver.find_element(By.CSS_SELECTOR, '#item3')  # #表示id标签        # 实现拖拽操作,.drag_and_drop(item_left, item_right)        ActionChains(self.driver).drag_and_drop(item_left, item_right).perform()    def test_hover(self):        """鼠标事件-悬浮"""        self.driver.get(";)        # 获取下拉框位置        ele = self.driver.find_element(By.CSS_SELECTOR, ".menu")        # 鼠标悬浮在下拉框        ActionChains(self.driver).move_to_element(ele).perform()        # 选择下拉选项        self.driver.find_element(By.XPATH, "//*[contains(text(),'测开班')]").click()        time.sleep(3)
5、滚轮/滚动操作滚动到元素 scroll_to_element(WebElement对象):滚动到某个元素根据坐标滚动 scroll_by_amount(横坐标, 纵坐标)注意: selenium 版本需要在 4.2 之后
import timefrom selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.common.by import Byclass TestScroll:    def setup_class(self):        self.driver = webdriver.Chrome()        self.driver.implicitly_wait(10)  # 隐式等待    def teardown_class(self):        self.driver.quit()    def test_scoll_to_element(self):        """滚轮/滚动操作-滚动到元素"""        # 打开网页        self.driver.get(";)        # 获取页面底部某个标题        ele = self.driver.find_element(By.XPATH, "//*[text()='接口测试上线标准']")        # 页面滚动操作,找到"接口测试上线标准",selenium版本需要在 4.2 之后        ActionChains(self.driver).scroll_to_element(ele).perform()        time.sleep(5)    def test_scroll_to_xy(self):        """滚轮/滚动操作-根据坐标滚动"""        self.driver.get(";)        # 坐标滚动方式,.scroll_by_amount(0, 10000)纵向滚动        ActionChains(self.driver).scroll_by_amount(0, 3000).perform()        time.sleep(3)
十二、网页 frame 与多窗口处理1、selenium⾥⾯如何处理多窗⼜场景多个窗口识别多个窗口之间切换2、selenium⾥⾯如何处理frame多个frame识别多个frame之间切换3、多窗口处理点击某些链接,会重新打开⼀个窗口,对于这种情况,想在新页⾯上操作,就得先切换窗口了。获取窗口的唯⼀标识⽤句柄表⽰,所以只需要切换句柄,就可以在多个页⾯灵活操作了。4、多窗口处理流程先获取到当前的窗口句柄(driver.current_window_handle)再获取到所有的窗口句柄(driver.window_handles)判断是否是想要操作的窗口,如果是,就可以对窗口进⾏操作,如果不是,跳转到另外⼀个窗口,对另⼀个窗口进⾏操作 (driver.switch_to_window)
"""base.py文件,Base类有前置和后置操作"""from selenium import webdriver# 前置和后置操作,提供测试用例调用class Base(object):    # 前置操作    def setup(self):        self.driver = webdriver.Chrome()        self.driver.implicitly_wait(5)  # 隐式等待    # 后置操作    def teardown(self):        self.driver.quit()"""测试用例文件test_window.py"""import timefrom selenium.webdriver.common.by import Byfrom webui.window_frame.base import Base# 继承Base类,Base类里有前置和后置操作class TestWindows(Base):    def test_window(self):        self.driver.get(";)        # 找到登录按钮,并点击        self.driver.find_element(By.XPATH, "//*[@id='s-top-loginbtn']").click()        print(self.driver.current_window_handle)   # 点击登录之后,打印当前窗口        # 点击弹窗里的立即注册按钮        self.driver.find_element(By.XPATH, "//*[text()='立即注册']").click()        # # 点击立即注册之后,打印当前窗口        # print(self.driver.current_window_handle)        # # 打印所有窗口的名字,列表形式,会有注册页面的窗口,        # print(self.driver.window_handles)        # 获取所有窗口列表,赋给window        window = self.driver.window_handles        # window[-1]获取注册页面的窗口,并切换到注册页面的窗口        self.driver.switch_to.window(window[-1])        # 注册页面,输入用户名username        self.driver.find_element(By.ID, "TANGRAM__PSP_4__userName").send_keys("username")        time.sleep(3)        # 切换回最初登录页面的窗口        self.driver.switch_to.window(window[0])        # # 登录页面,点击短信登录        # self.driver.find_element(By.XPATH, "//*[text()='短信登录']").click()        # 获取用户名输入框,并输入用户名        self.driver.find_element(By.ID, "TANGRAM__PSP_11__userName").send_keys("login_username")        # 获取密码输入框,并输入密码        self.driver.find_element(By.ID, "TANGRAM__PSP_11__password").send_keys("login_password")        # 点击登录        self.driver.find_element(By.ID, "TANGRAM__PSP_11__submit").click()        time.sleep(6)
5、frame处理
1)frame介绍    ①在web⾃动化中,如果⼀个元素定位不到,那么很⼤可能是在iframe中。    ②什么是frame?        a. frame是html中的框架,在html中,所谓的框架就是可以在同⼀个浏览器中显⽰不⽌⼀个页⾯。        b. 基于html的框架,又分为垂直框架和⽔平框架(cols,rows)    ③Frame 分类        a. frame标签包含frameset、frame、iframe三种,        b. frameset和普通的标签⼀样,不会影响正常的定位,可以使⽤index、id、name 、webelement任意种⽅式定位frame。        c. ⽽frame与iframe对selenium定位⽽⾔是⼀样的。selenium有⼀组⽅法对frame进⾏操作2)多frame切换    ①frame存在两种:⼀种是嵌套的,⼀种是未嵌套的    ②切换frame        ❖ driver.switch_to.frame() # 根据元素id或者index切换切换frame        ❖ driver.switch_to.default_content() # 切换到默认frame        ❖ driver.switch_to.parent_frame() # 切换到⽗级frame3)frame未嵌套    ①处理未嵌套的iframe        ❖ driver.switch_to_frame(“frame 的 id”)        ❖ driver.switch_to_frame(“frame - index”) frame⽆ID的时候依据索引来处理,索引从0开始 driver.switch_to_frame(0)4)frame嵌套    ②处理嵌套的iframe        ❖ 对于嵌套的先进⼊到iframe的⽗节点,再进到⼦节点,然后可以对⼦节点⾥⾯的对象进⾏处理和操作        ❖ driver.switch_to.frame(“⽗节点”)        ❖ driver.switch_to.frame(“⼦节点”)
import timefrom selenium.webdriver.common.by import Byfrom webui.window_frame.base import Base# 继承Base类,Base类里有前置和后置操作class TestFrame(Base):    def test_frame(self):        self.driver.get(";)        # 切换到frame中,根据frame的元素id        self.driver.switch_to.frame("iframeResult")  # 写法一,常用        # self.driver.switch_to_frame("iframeResult")  # 写法二        # 获取"请拖拽我!"的属性,获取文本内容        print(self.driver.find_element(By.ID, "draggable").text)        # 写法一:切回网页,即不在frame页面,即切回frame父节点        # self.driver.switch_to.parent_frame()        # 写法二:切换到默认frame节点,即刚打开的地址节点        self.driver.switch_to.default_content()        # 获取"点击运行"按钮,并点击        self.driver.find_element(By.ID, "submitBTN").click()        time.sleep(5)
十三、文件上传弹框处理1、⽂件上传input标签可以直接使⽤send_keys(⽂件地址)上传⽂件⽤法: el = driver.find_element_by_id('上传按钮id') el.send_keys(”⽂件路径+⽂件名")
import timefrom selenium.webdriver.common.by import Byfrom webui.window_frame.base import Base# 继承Base类,Base类里有前置和后置操作class TestFile(Base):    def test_file_upload(self):        self.driver.get(";)        # 找到百度的相机图标并点击        self.driver.find_element(By.XPATH, "//*[@class='soutu-btn']").click()        # 定位到选择文件,并选择文件        self.driver.find_element(By.XPATH, "//input[@class='upload-pic']").send_keys("/Users/jiyu/PycharmProjects/pythonProject/webui/img/12.png")        time.sleep(5)
2、chrome 开启 debug 模式有时候登录⽅式⽐较繁琐,需要动态⼿机密码,⼆维码登录之类的。⾃动话实现⽐较⿇烦。⼿⼯登录后,不想让selenium启动⼀个新浏览器。可以使⽤chrome的debug⽅式来执⾏测试。启动chrome的时候需要先退出所有chrome进程。使⽤ps aux|grep chrome|grep -v 'grep'查看是否有chrome进程存在。确保没有chrome进程被启动过。正常启动chrome的debug模式 默认macOS系统 /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debuggingport=9222 Windows下找到chrome.exe位置执⾏下⾯的命令 chrome.exe --remote-debugging-port=9222启动后的提⽰信息,代表chrome运⾏正常,不要关闭⾃动打开的chrome窗口。3、弹框处理机制在页⾯操作中有时会遇到JavaScript所⽣成的alert、confirm以及prompt弹框,可以使⽤switch_to.alert()⽅法定位到。然后使⽤text/accept/dismiss/send_keys等⽅法进⾏操作。操作alert常⽤的⽅法: switch_to.alert():获取当前页⾯上的警告框。 text:返回alert/confirm/prompt 中的⽂字信息。 accept():接受现有警告框。 dismiss():解散现有警告框。 send_keys(keysToSend):发送⽂本⾄警告框。keysToSend:将⽂本发送⾄警告框。
import timefrom selenium.webdriver import ActionChainsfrom selenium.webdriver.common.by import Byfrom webui.window_frame.base import Baseclass TestAlert(Base):    def test_alert(self):        """        ❖ 打开⽹页         ❖ 操作窗⼜右侧页⾯, 将元素1拖拽到元素2        ❖ 这时候会有⼀个alert弹框,点击弹框中的’确定’        ❖ 然后再按’点击运⾏’        ❖ 关闭⽹页        :return:        """        self.driver.get(";)        # 切换到frame中,根据frame的元素id        self.driver.switch_to.frame("iframeResult")        # 获取需要拖动的元素,即起始元素的位置        a1 = self.driver.find_element(By.CSS_SELECTOR, '#draggable')        # 获取目标元素的位置        a2 = self.driver.find_element(By.CSS_SELECTOR, '#droppable')        # 实现拖拽操作,.drag_and_drop(a1, a2):将a1拖拽到a2上,.perform()执行        action = ActionChains(self.driver)        action.drag_and_drop(a1, a2).perform()        time.sleep(2)  # 强制等待2秒,查看效果        # 切换到alert页面,点击alert的确认按钮.accept()        self.driver.switch_to.alert.accept()        # 退出alert页面,返回到默认frame节点        self.driver.switch_to.default_content()        # 获取"点击运行"按钮,并点击        self.driver.find_element(By.ID, 'submitBTN').click()        time.sleep(3)
十四、自动化关键数据记录1、什么是关键数据代码的执行日志代码执行的截图page source(页面源代码)2、记录关键数据的作用

内容

作用

日志

1. 记录代码的执行记录,方便复现场景;2. 可以作为bug依据

截图

1. 断言失败或成功截图;2.异常截图达到丰富报告的作用;3. 可以作为bug依据

page source

1. 协助排查报错时元素当时是否存在页面上

3、行为日志记录日志配置脚本日志级别 debug记录步骤信息 info记录关键信息,比如断言等

#日志配置文件log_utils.py# 日志配置import logging# 创建logger实例logger = logging.getLogger('simple_example')# 设置日志级别logger.setLevel(logging.DEBUG)# 流处理器ch = logging.StreamHandler()ch.setLevel(logging.DEBUG)# 日志打印格式formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 添加格式配置ch.setFormatter(formatter)# 添加日志配置logger.addHandler(ch)
# 测试用例脚本文件test_data_record.py# 日志与脚本结合from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom webui.data_record.log_utils import loggerfrom webui.window_frame.base import Base# 继承Base类,Base类里有前置和后置操作class TestDataRecord(Base):    """"""    def test_data_record(self):        search_content = "python语言"        # 打开网页        self.driver.get(";)        # 定位输入框,输入内容        self.driver.find_element(By.ID, "query").send_keys(search_content)        # 加入日志,步骤信息较多且琐碎,使用debug        logger.debug(f"搜索的信息为:{search_content}")        # 点击搜索        self.driver.find_element(By.ID, "stb").click()        # 获取搜索结果列表的标题,对应测试结果的实际结果        search_result = self.driver.find_element(By.CSS_SELECTOR, "em")  # 多个em的情况下,默认拿第一个        # 添加日志,断言使用info,级别高于debug,断言实际结果与预期结果是否一致        logger.info(f"实际结果为:{search_result.text},预期结果为:{search_content}")        # 断言,search_result.text 获取搜索结果的文本信息,预期结果search_content        assert search_result.text == search_content
4、步骤截图记录save_screenshot(截图路径+名称)记录关键页面 断言页面 重要的业务场景页面 容易出错的页面
from selenium.webdriver.common.by import Byfrom webui.data_record.log_utils import loggerfrom webui.window_frame.base import Base# 继承Base类,Base类里有前置和后置操作class TestDataRecord(Base):    def test_screen_shot_data_record(self):        search_content01 = "python语言"        # 打开网页        self.driver.get(";)        # 定位输入框,输入内容        self.driver.find_element(By.ID, "query").send_keys(search_content01)        # 加入日志,步骤信息较多且琐碎,使用debug        logger.debug(f"搜索的信息为:{search_content01}")        # 点击搜索        self.driver.find_element(By.ID, "stb").click()        # 获取搜索结果列表的标题,对应测试结果的实际结果        search_result01 = self.driver.find_element(By.CSS_SELECTOR, "em")  # 多个em的情况下,默认拿第一个        # 添加日志,断言使用info,级别高于debug,断言实际结果与预期结果是否一致        logger.info(f"实际结果为:{search_result01.text},预期结果为:{search_content01}")        # 截图记录,双重保障        self.driver.save_screenshot("search_result01.png")        # 断言,search_result01.text 获取搜索结果的文本信息,预期结果search_content01        assert search_result01.text == search_content01
5、page source记录使用page_source属性获取页面源码在调试过程中,如果有找不到元素的错误可以保存当时的page_source调试代码
from selenium.webdriver.common.by import Byfrom webui.window_frame.base import Base# 继承Base类,Base类里有前置和后置操作class TestDataRecord(Base):    def test_page_source_data_record(self):        """获取page_source主要用于调试,可以不需要断言等其余信息"""        # 现象:产生了no such element的错误        # 方案:在报错的代码行之前打印page_source,确认定位的元素没有问题        content = "python语言"        # 打开网页        self.driver.get(";)        # # 定位输入框,输入内容        # self.driver.find_element(By.ID, "query").send_keys(content)        # 获取page_source,即获取的是这个网页的源代码        # logger.debug(self.driver.page_source)  # 可以使用debug查看输出的内容        # 将获取的page_source写入到record.html        with open("record.html", "w", encoding="utf-8") as f:            f.write(self.driver.page_source)        # 错误定位输入框        self.driver.find_element(By.ID, "query1").send_keys(content)
点此获取更多相关资料>「链接」

标签: #jquery寻找邻近节点