?作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。
?主页地址:【Austin_zhai】
?目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。
?声明:博主日常工作较为繁忙,文章会不定期更新,各类行业或职场问题欢迎大家私信,有空必回。
阅读目录
1. 目的2. 说明3. 关于解答上一篇的问题4. 启动5. 浏览器基础操作5.1 浏览器窗口操作5.2 页面基础操作5.3 信息操作5.4 元素操作5.4.1 name定位5.4.2 class name定位5.4.3 id定位5.4.4 css定位5.4.5 link text定位5.4.6 partial link text定位5.4.7 tag定位5.4.8 xpath定位 5.5 延时方式5.5.1 隐式等待5.5.2 显式等待5.5.3 强制等待 5.6 超时等待5.7 键鼠操作5.8 组件操作5.9 鉴权操作5.9 js操作 6. 注意点与小技巧
1. 目的
web自动化测试作为软件自动化测试领域中绕不过去的一个“香饽饽”,通常都会作为广大测试从业者的首选学习对象,相较于C/S架构的自动化来说,B/S有着其无法忽视的诸多优势,从行业发展趋、研发模式特点、测试工具支持,其整体的完整生态已经远远超过了C/S架构方面的测试价值。接上一篇文章,我们将继续深入探讨Selenium的相关使用方法与技巧。
2. 说明
此篇中所用的技术栈为Selenium+Python,因其本身编程难度不高,总体思想都是基于面向对象的编程理念,故只要大家的编码语言基础不弱,就完全可以做到平替。
3. 关于解答上一篇的问题
在正式启动浏览器之前,这里还需要说说上一篇没有提及的一个问题,后台有同学私信说在对应驱动网站上完全找不到自己浏览器对应版本的驱动,关于浏览器驱动的版本,大家都知道驱动的版本应该是要与浏览器的版本完全对应上的。但往往日常工作中因为环境或者其他客观因素会导致浏览器的版本五花八门,也会出现驱动网站上完全没有你目前工作环境中对应的浏览器版本,这里我们大可使用中版本号一致的驱动来进行尝试,没有必要将版本进行完全的匹配。比如你的Chrome浏览器的版本号为107.0.5304.107
,如果这时对应网站只有107.0.5304.62
与108.0.5359.22
的前后两个版本的驱动比较相近,这里就有两个选择,第一就是卸掉原有的浏览器,安装对应的版本;第二则是选择107.0.5304.62
来进行尝试;相信大家在成本耗时的判断下,一般都会选择第二个选项来进行尝试对吧?那么我可以很负责任的告诉你,第二个判断是完全行的通的。不必太过纠结驱动的小版本号是否完全匹配。
4. 启动
我们将一切准备就绪后就可以开始我们的selenium之旅了,首先我们需要将使用selenium进行浏览器的启动(访问百度)。
from selenium import webdriverbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')
如果对应的浏览器驱动没有进行环境变量的设置,可以在代码中直接进行程序的路径指定来进行后续的浏览器操作。
from selenium import webdriverpath = r'C:\Program Files\Google\Chrome\Application\chromedriver.exe'browser = webdriver.Chrome(path)browser.get('https://www.baidu.com')
使用Selenium打开后的浏览器都会标识出正在受到自动化测试软件控制的相关提示。
5. 浏览器基础操作
Selenium本身提供给了我们非常多的各类浏览器与页面的操作函数,方便我们根据所需测试业务来进行自由搭配使用甚至是二开。
5.1 浏览器窗口操作
对于浏览器窗口的尺寸进行控制与获取,如最大化、最小化、指定窗口大小等。
窗口全屏
browser.fullscreen_window()
窗口最大化
browser.maximize_window()
窗口最小化
browser.minimize_window()
自定义窗口大小(宽X高)
browser.set_window_size(1080, 720)
自定义窗口坐标位置与大小(x坐标,y坐标,宽X高)
browser.set_window_rect(100, 200, 1080, 720)
获取窗口的大小(宽X高)
browser.get_window_size()
获取窗口的坐标位置,返回一个字典对象
browser.get_window_position()
获取窗口的坐标与大小(x坐标,y坐标,宽X高)
browser.get_window_rect()
获取当前窗口的句柄
browser.current_window_handle
获取当前所有窗口的句柄
browser.window_handles
5.2 页面基础操作
对于浏览器当前页面的一些操作,如前进、后退、刷新等。
前进(下一页面)
browser.forward()
后退(上一页面)
browser.back()
刷新(当前页面)
browser.refresh()
截图并保存为test.png(当前页面)
browser.save_screenshot('test.png')
截图并保存为png文件(当前页面)
browser.get_screenshot_as_file('test_02.png')
截图并将信息转为base64编码的字符串
browser.get_screenshot_as_base64()
5.3 信息操作
对于浏览器当前一些信息的获取与操作。
获取页面URL(当前页面)
browser.current_url
获取日志类型,会返回一个列表对象
browser.log_types
获取浏览器操作日志,注意函数内的参数为固定值类型’browser’
browser.get_log('browser')
获取设备操作日志,参数原理同上
browser.get_log('driver')
获取当前页面标题
browser.title
获取当前浏览器的名字
browser.name
5.4 元素操作
Selenium中最基础也是最重要的一环,基本上对于页面的业务操作大多数都集中与此。另外需要注意的是元素定位所使用的find_element_by的方法在很早之前就已经被废弃,这里同样也会使用最新的find_element方法进行讲解。
如何查看页面中的元素与其相关属性,这里以Chrome为例,我们只需按F12或者右键页面选择“检查”,再点击调试窗口的左上角的箭头标志或者使用快捷键Ctrl+Shift+C
来进行元素的选取,此时Elements标签页中会将焦点对应跳转至该元素的html代码行中,接下来我们就可以针对不同的元素和不同的属性来进行定位操作。
5.4.1 name定位
通过一个元素的name属性来进行定位。
比如定位百度中的搜索栏,我们通过name属性来进行定位。该元素的html构造如下:
<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off">
我们只需将name属性后面的值拿出,赋予给find_element方法即可。新的By方法我们只需要导入selenium.webdriver.common.by下的By方法即可。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.NAME, 'wd')
5.4.2 class name定位
通过一个元素的class属性来进行定位。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.CLASS_NAME, 's_ipt')
5.4.3 id定位
通过一个元素的id属性来进行定位。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.ID, 'kw')
5.4.4 css定位
css selector也被成为选择器定位,它通过页面内的元素的id、name、tag三个属性来进行定位,根据元素属性的重复程度,可以单独属性定位也可组合属性来进行定位。而且相较于xpath定位方式来说,博主更推荐使用此方法来进行定位,无论是易用度还是维护性来说比xpath定位好的多。
单属性定位–tag属性
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.CSS_SELECTOR, 'input')
单属性定位–id属性
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.CSS_SELECTOR, '#kw')
单属性定位–class属性
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.CSS_SELECTOR, '.s_ipt')
多属性定位–tag+id属性
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.CSS_SELECTOR, 'input#kw')
多属性定位–tag+class属性
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.CSS_SELECTOR, 'input.s_ipt')
同样的,其他的组合方式大家可以举一反三,不断尝试,比如模糊匹配input[class ~= "局部关键字"]
、层级定位#form > span > input
等等等等。
5.4.5 link text定位
这种定位方式适用于页面中带有超链接的元素,直接通过超链接标签内的文字进行元素定位。
我们以百度首页为例,可以看到该页面中有很多的超链接标签,如果我们想模拟点击跳转至新闻对应页面的操作,就可以用link text的元素定位方法来进行实现。
使用超链接标签对中的“新闻”一词来进行定位。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.LINK_TEXT, '新闻').click()
5.4.6 partial link text定位
这个定位方式与link text定位十分相像,实际上也就是link text的模糊查找定位方式,对象也是超链接内的文字,只不过他匹配的不是全部文字而是局部。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.PARTIAL_LINK_TEXT, '新').click()
5.4.7 tag定位
tag定位的效率总体来说不高,也不太推荐单独使用,html页面中一般也是由很多相同或不同的标签对组成。就tag而言标签重复的越多,定位的效率其实也就越低。
比如我们想在百度的搜索栏中输入“selenium”关键字,那么光使用tag其实就很难达到我们的目的,甚至无法准确定位到我们想要的元素。如果运气好,搜索栏的input标签在html页面中排在第一位那还好,只要不是第一位,我们就需要编写其他的代码逻辑来辅助我们继续定位这个元素。
所以下面的代码实在是不能称之为高效的执行代码
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.TAG_NAME, 'input').send_keys('selenium')
5.4.8 xpath定位
一般来说无法通过以上的这些元素定位方法定位的情况下,我们会使用xpath定位方法。但这里需要特别注意,xpath方法分为绝对路径和相对路径两种定位方式,博主只推荐如果真要使用xpath就使用相对路径+正则表达式的方式来进行元素定位。不推荐绝对路径的原因就不用博主多说了吧,只要你敢用,后期的脚本维护与复用绝对会让你抓狂的。
还是老样子,我们使用xpath的相对路径写法来定位百度首页的搜索栏。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.XPATH, '//*[@id="kw"]').send_keys('selenium')
另外与find_element方法相对应的find_elements方法这里就不多做介绍了,该种方法是将当前页面中所有能匹配上对应元素定位方法的元素全部获取。大家可以根据自己的需求来进行选取和使用。
5.5 延时方式
我们加载页面时通常会因为网络环境等各方面的客观因素而导致元素加载的速度各不相同,如果此时我们没有对业务操作进行一定的延时执行,那么大概率业务操作会出现各类的no such element
报错。
那么我们就需要在页面元素加载完成之后再对相应的元素进行业务操作来规避上面说的这个问题。Selenium内可以使用三种延时的函数来进行对应的延时业务操作。
5.5.1 隐式等待
隐式等待的作用是在页面加载是隐性的进行特定时长的等待,如果在规定的等待时长内页面加载完毕,则会继续进入下一个业务操作,如果没有加载完毕,则会抛出一个超时的异常。这里其实有两个问题,第一,隐式等待是全局性质的,也就是说一旦你设置了个5秒,那整个程序都会使用这个等待时间类进行配置,灵活性较低;第二,如果碰到了有些页面中的元素是局部加载的话,那整个页面的加载是否完成也就没有了其意义,隐式加载无法针对这样的情况作出调整,智能度较低。所以一般来说只要是对于页面的整体加载要求不高或者元素的加载比较稳定的程序,都可以使用隐式等待来进行延时操作。
from selenium import webdriverfrom selenium.webdriver.common.by import Bybrowser = webdriver.Chrome()browser.get('https://www.baidu.com')browser.implicitly_wait(5)browser.find_element(By.XPATH, '//*[@id="kw"]').send_keys('selenium')
5.5.2 显式等待
显式等待的作用则是使用特定的等待时长来进行某些业务逻辑判断,如果判断(比如元素是或否加被定位)在时间完成那继续执行下一个业务操作,如果判断失败也会抛出no such element的异常,而显式等待的默认检查元素周期为0.5秒。乍一看好像与隐式等待差不多,其实不然,首先显式等待是针对页面中某个或某组特定元素而执行的,隐式则是全局,对所有的元素都生效;其二,显式等待可以通过自定义条件来进行元素的定位和选取,隐式则不行。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')ele = WebDriverWait(browser, 10, 0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="kw"]')))ele.send_keys('selenium')
5.5.3 强制等待
这个应该是平时大家代码中用的最多的等待方式了吧,sleep是针对线程进行挂起的一种等待方式,等待时长根据指定的参数来进行决定。最大的好处就是简单粗暴,无任何逻辑在里面,所以也被称为强制等待。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')sleep(2)browser.find_element(By.XPATH, '//*[@id="kw"]').send_keys('selenium')
那么以上的三种等待方式其实各有各的特点与缺点,三者之间没有绝对的好用和不好用,而在我们的日常工作场景中也希望大家可以根据实际的情况有选择性的使用。
5.6 超时等待
元素加载超时我们可以使用以上三种延时方式来进行处理,那么页面超时了又该如何操作呢?selenium也为我们准备了两个函数来对应这样的局面。
页面加载超时
browser.set_page_load_timeout(30)
这里推荐将超时的时间有效的拉长,不宜过短。过短的超时时间容易导致整体页面出现未加载html代码情况下直接令驱动无法工作的情况。
页面异步js或ajax操作超时
browser.set_script_timeout(30)
这个函数是用于execute_async_script()
相关的异步js操作超时报错,由于是异步操作,等待时间同理也不易过短。
5.7 键鼠操作
浏览器中键盘与鼠标的操作也是不可或缺的重要一环,在被测对象的业务要求中往往占有不少的戏份。
文字输入
browser.find_element(By.ID, 'kw').send_keys('selenium')
点击
browser.find_element(By.ID, 'kw').click()
点击并按住不放(左键长按),这些模拟鼠标操作需要导入ActionChains包
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw')act.click_and_hold(ele).perform()
右键点击
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw')act.context_click(ele).perform()
双击
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw')act.double_click(ele).perform()
拖拽元素至另一个元素处,ele_a 为source,ele_b 为target
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele_a = browser.find_element(By.ID, 'btn_a')ele_b = browser.find_element(By.ID, 'btn_b')act.drag_and_drop(ele_a, ele_b).perform()
拖拽元素至指定位置后松开,元素后为x,y坐标值
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'btn_a')act.drag_and_drop_by_offset(ele, 200, 100).perform()
鼠标移动至指定元素
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'btn_a')act.move_to_element(ele).perform()
按下指定的键位(示例代码中是回车键)
from selenium import webdriverfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw').send_keys('selenium')act.key_down(Keys.ENTER).perform()
松开指定的键位,这里也可以用链式写法
from selenium import webdriverfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw').send_keys('selenium')act.key_down(Keys.ENTER)act.key_up(Keys.ENTER)# 链式写法act.key_down(Keys.ENTER).act.key_up(Keys.ENTER).perform()
移动鼠标到指定坐标位置
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw').send_keys('selenium')act.move_by_offset(100, 200).perform()
移动到距离指定元素多少距离的位置(从左上角0, 0开始计算)
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw').send_keys('selenium')act.move_to_element_with_offset(ele, 100, 200).perform()
在指定元素位置松开鼠标
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw').send_keys('selenium')act.click_and_hold(ele).release(ele).perform()
发送指定的键或者内容至指定元素
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw').send_keys('selenium')act.send_keys_to_element(ele, 'selenium').perform()
暂停所有操作,默认单位为秒
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw').send_keys('selenium')act.context_click(ele).pause(5).double_click(ele).perform()
5.8 组件操作
页面中也存在着很多不同种类的组件,比如单选框、多选框、下拉列表、选项卡等。这些操作也可以通过selenium提供的函数进行实现。
清除指定元素中的内容(输入框等)
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw')ele.send_keys('selenium')sleep(2)ele.clear()
提交确认(类似于Keys.ENTER的效果)
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsfrom time import sleepbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')act = ActionChains(browser)ele = browser.find_element(By.ID, 'kw')ele.send_keys('selenium')sleep(2)ele.submit()
下拉列表,我们就可以使用Select方法来实现选取操作
使用Select方法需要从selenium.webdriver.support.select导入该方法
例如下图中某网站的下拉列表对象
html构造如下
select_by_index()方法
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.select import Selectbrowser = webdriver.Chrome()browser.get('https://www.xxxx.com')ele = browser.find_element(By.ID, 'input_factor_gj_count')# 需要注意下标要从0开始,选择1%那一项Select(ele).select_by_index('0')
select_by_value()方法
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.select import Selectbrowser = webdriver.Chrome()browser.get('https://www.xxxx.com')ele = browser.find_element(By.ID, 'input_factor_gj_count')# 指定元素的value属性值,选择1%那一项Select(ele).select_by_value('0.01')
select_by_value()方法
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.select import Selectbrowser = webdriver.Chrome()browser.get('https://www.xxxx.com')ele = browser.find_element(By.ID, 'input_factor_gj_count')# 指定元素的文本值,选择1%那一项Select(ele).select_by_visible_text('1%')
框架切换(Frame)
如果在页面中定位某一个元素失败并检查其属性并没有问题时,就该考虑是否在祖先节点中是否存在frame或者iframe标签。这样的页面就表名存在多层框架嵌套,这时我们就需要进行框架切换的操作,来准确定位到指定元素。
例如某页面存在两层frame嵌套,内部框架的xpath为://*[@id="mainDiv"]/iframe
,此时如果定位某个输入框失败之后,我们就应该转而跳入该frame内进行元素定位。
from selenium import webdriverfrom selenium.webdriver.common.by import Bybrowser = webdriver.Chrome()browser.get('https://www.xxxx.com')# 定位到指定的framepath = browser.find_element(By.XPATH, '//*[@id="mainDiv"]/iframe')# 切换至该frame内browser.switch_to_frame(path)ele = browser.find_element(By.CLASS_NAME, 'input')ele.send_keys('selenium')
标签页切换
我们浏览器在使用中一般会打开多个浏览窗口,也就是多个标签页。此时我们就可以通过每个标签页的句柄来进行定位和互相切换。
switch_to_window()
我们利用浏览器窗口的句柄来进行标签页的切换
from selenium import webdriverfrom selenium.webdriver.common.by import Bybrowser = webdriver.Chrome()browser.get('https://www.baidu.com')# 第一个窗口的句柄下标为0,打开第二个就是1browser.switch_to_window(browser.window_handles[1])# 此时就会使用第二个标签页去访问淘宝browser.get('https://www.taobao.com')
弹窗处理
页面中时常也存在着各类的弹窗,比如警告、确认、提示等等,那么对于这些弹窗我们也有着相应的业务处理方法。
首先我们需要明确的是每种类型的弹窗中元素也是各不相同,所以我们针对不同的弹窗使用不同的属性来定位和操作。
警告弹窗
一般来说就是告知到使用者执行某些操作与页面之后将要注意的事项,这种窗口只需确认。
from time import sleepfrom selenium import webdriverfrom selenium.webdriver.common.by import Bybrowser = webdriver.Chrome()browser.get('https://www.xxxx.com')browser.find_element(By.ID, 'btn_tg_title').click()sleep(1)# 在警告弹窗中点击确认按钮browser.switch_to_alert().accept()
确认弹窗
多用于在用户执行提交操作后的动作确认,有确认和取消两个选项。
from time import sleepfrom selenium import webdriverfrom selenium.webdriver.common.by import Bybrowser = webdriver.Chrome()browser.get('https://www.xxxx.com')browser.find_element(By.ID, 'btn_submit').click()sleep(1)#确认二选一browser.switch_to_alert().accept()#取消二选一browser.switch_to_alert().dismiss()
提示弹窗
这个通常用来处理用户信息交互的场景,用户可以通过弹窗输入一些文字信息,来传递与进行后续的业务处理。
from time import sleepfrom selenium import webdriverfrom selenium.webdriver.common.by import Bybrowser = webdriver.Chrome()browser.get('https://www.xxxx.com')browser.find_element(By.ID, 'btn_info_inquiry').click()sleep(1)# 这里传递信息到提示弹窗,警告与确认两类弹窗不可使用,会报错browser.switch_to_alert().send_keys('20100909')
5.9 鉴权操作
既然是web自动化测试,那我们又怎么能少了Cookie的相关操作呢?用户的状态和业务请求都的需要用他来进行鉴权。在selenium中对Cookie进行操作其实也很简单,首先我们需要手动的登录被测网站一次,待网站Cookie存入本地后即可使用Selenium自带的函数对齐进行业务操作。
首先我们获取对应网站的Cookie值
import jsonfrom selenium import webdriverbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')# 写入保存为文件还是直接打印至控制台,各取所需with open('cookies.txt', 'w') as f: f.write(json.dumps(browser.get_cookies()))cookies = browser.get_cookies()print(cookies)
接下来我们简单的对获得的Cookie进行处理
# 删除所有的cookiesbrowser.delete_all_cookies()# 循环打印cookie中的name和valuefor c in cookies:# 查看打印出的cookie对应的键值对 print("%s : %s" % (c['name'], c['value']))# 根据自己的业务需求进行cookie的增删改cookie = {"name": "xxxx", "value": "xxxx"}# 最后添加即可driver.add_cookie(cookie)
5.9 js操作
Selenium也为我们提供了可执行js脚本相关的函数,他们的作用是在某些页面中模拟一些业务动作(画面滑动,选择日期等)。在一些仅靠webdriver无法实现的业务场景中,我们就可以依靠此函数来辅助测试目的的达成。
js的查找元素方法(ID)
document.getElementById("id")
js的查找元素方法(name)
document.getElementsByName('name')
js的查找元素方法(class)
document.getElementsByClassName("class_name")
js的查找元素方法(tag)
document.getElementsByTagName('tag_name')
js的查找元素方法(css)
document.querySelector("css selector")
js的查找元素方法(css_list)
document.querySelectorAll("css selector")
execute_script()
从上可以看出其实js的定位元素方法和selenium中的差不多,接下来我们就可以将需要执行的js语句放入到执行函数中使用。
from selenium import webdriverbrowser = webdriver.Chrome()browser.get('https://www.baidu.com')# 定位后修改指定元素的value属性js_script_exec = 'document.getElementById("form_motion").value="list_modify";'browser.execute_script(js_script_exec)
6. 注意点与小技巧
对于某些动态div标签(窗口),一般的方法不太奏效的情况下,可以尝试下switch_to_default_content()方法,跳转到最外层;
使用模拟键鼠操作的时候,无论是单独使用还是链式写法,记得在结尾加上perform()方法进行执行;
如果元素定位时报错element click intercepted,记得检查界面上是否有其他元素进行覆盖,元素有可能也是具有隐藏属性的;
元素过期报错element is not attached to the page document,可以尝试重新刷新页面,这里不推荐直接使用refresh方法,还是养成好习惯先怼上try…except…捕捉到异常后在进行刷新或重置操作;
对于属性值为动态的元素,墙裂推荐使用CSS selector或者xpath方法来进行元素定位,正则表达式也推荐大家最好能掌握;
如果前期对xpath的相对路径写法比较头疼,推荐使用F12调试工具自带的元素复制功能,在你想要复制的元素所在的标签对这行右键,选择copy —— Copy XPath选项即可;
输入框默认存在内容想要删除再输入信息的话,不推荐模拟键盘操作Ctrl+A,然后模拟退格键,试试clear()方法吧;
抓不到元素可以使用延时方法,输入文字也是一样的道理,业务场景中需要大量输入文字的,无论是从文件中还是提取又或者是遍历,出现少字漏字的话,同样也可以使用延时的方法,适当的放慢处理的速度;
在页面中总会有些不可见的元素,这种情况使用is_displayed()方法即可快速定位找到;
有些被测页面需要验证码,无论是手机的还是图片验证,和开发同学沟通一下,留个万能的就行了,其本身的功能手工回归一下即可,不必太过纠结;
三方登录功能也是如此,不推荐直接使用web自动化去搞,三方的一般是不开源的,有这折腾的时间还不如跑跑接口和黑盒,自动化的话绕过去即可;
自动化测试用例这块的话博主还是推荐不要有依赖,和功能测试用例同理,每次的执行顺序或者数量都会根据需求与业务场景发生变化,一旦依赖了会大大增加测试同学的维护成本,后面有空我会单独出一期自动化测试用例的文章来为大家介绍。