【Selenium学习】WebDriverApi接口和二次开发
WebDriverApi接口详解
浏览器操作
1 driver.back() # 后退 2 driver.forward() # 前进 3 driver.refresh() # 刷新
窗口操作
1 driver.get_window_size() # 获取浏览器大小 2 driver.set_window_size('500','500') # 设置浏览器大小 3 driver.maximize_window() # 最大化浏览器 4 driver.current_window_handle() # 返回当前操作的浏览器句柄 5 driver.window_handles() # 返回所有打开server的浏览器句柄
截取当前页面(截图)
1 driver.get_screenshot_as_file('pic.png') # 文件名必须以小写的.png结尾
执行JavaScript语句
1 driver.execute_script('JavaScript Commond') 2 driver.execute_script('window.scrollTo(0,0);') # 操作滚动条到浏览器最上面
Cookie操作
1 # 根据cookieKey,获取cookie信息 2 cookie = driver.get_cookie('cookieKey') 3 4 # 获取所有cookie信息 5 cookies = driver.get_cookies() 6 7 # 添加cookie,严格按照格式添加,cookie的key为name,value为value 8 driver.add_cookie({'name': 'tmp', 'value': '123123123'}) 9 10 # 删除所有cookie信息 11 driver.delete_all_cookies() 12 13 # 根据cookieKey删除对应cookie 14 driver.delete_cookie('UiCode')
浏览器句柄及切换
1 print(driver.window_handles) # 获取所有打开server的浏览器句柄,返回的是一个list 2 bl = driver.find_element_by_css_selector('[href="/new-index/"]') 3 bl.click() # 点击连接打开一个新的页面 4 print(driver.window_handles) # 再次获取所有打开server的浏览器句柄 5 handes = driver.window_handles 6 driver.switch_to.window(handes[1]) # 切换浏览器句柄到新打开的这个页面 7 cl = driver.find_element_by_css_selector('#newtag') 8 cl.send_keys('AAAA') 9 driver.close() # 关闭当前指针指向句柄的页面 10 driver.switch_to.window(handes[0]) # 手动将浏览器指针切换回之前的页面 11 driver.find_element_by_css_selector('#i1').send_keys('EEEE') 12 driver.quit() # 关闭所有页面
关闭与退出
1 driver.close() # 关闭当前页面,关闭页面后如果指针切换了,必须手动切回来 2 driver.quit() # 关闭所有页面,退出驱动
ElementApi接口
1 # 根据标签属性名称,获取属性value 2 element.get_attribute('style') 3 4 # 向输入框输入字符串 如果input的type为file类型 可以输入文件绝对路径上传文件 5 element.send_keys() 6 7 # 清除文本内容 8 element.clear() 9 10 # 鼠标左键点击操作 11 element.click() 12 13 # 通过属性名称获取属性 14 element.get_property('id') 15 16 # 返回元素是否可见 True or False 17 element.is_displayed() 18 19 # 返回元素是否被选中 True or False 20 element.is_selected() 21 22 # 返回标签元素的名字 23 element.tag_name 24 25 # 获取当前标签的宽和高 26 element.size 27 28 # 获取元素的文本内容 29 element.text 30 31 # 模仿回车按钮 提交数据 32 element.submit() 33 34 # 获取当前元素的坐标 35 element.location 36 37 # 截取图片 38 element.screenshot()
弹框处理
1 driver.find_element_by_css_selector('#confirm').click() # 点击按钮,弹出弹框 2 print(driver.switch_to.alert.text) # 打印弹框返回的文本文字 3 driver.switch_to.alert.accept() # 确认 4 driver.switch_to.alert.dismiss() # 取消
常见异常
1 NoSuchElementException:没有找到元素 2 3 NoSuchFrameException:没有找到iframe 4 5 NoSuchWindowException:没找到窗口句柄handle 6 7 NoSuchAttributeException:属性错误 8 9 NoAlertPresentException:没找到alert弹出框 10 11 ElmentNotVisibleException:元素不可见 12 13 ElementNotSelectableException:元素没有被选中 14 15 TimeoutException:查找元素超时
ActionChainsApi接口详解
UI自动化测试过程中,经常遇到那种,需要鼠标悬浮后,要操作的才会元素出现的这种场景,那么我们就要模拟鼠标悬浮到某一个位置,做一系列的连贯操作,Selenium给我们提供了ActionChains模块。
引入方式
1 from selenium.webdriver.common.action_chains import ActionChains
move_to_element
1 # 鼠标移动到某一个元素上,结束elementObj 2 ActionChains(driver).move_to_element(e) 3 4 # 鼠标移动到制定的坐标上,参数接受x,y 5 ActionChains(driver).move_by_offset(e['x'], e['y']) 6 7 例: 8 # 鼠标悬浮操作 9 from selenium.webdriver.common.action_chains import ActionChains 10 fl = driver.find_element_by_css_selector('#a') # 获取鼠标要悬浮的元素 11 dis1 = driver.find_element_by_css_selector('#dis1') # 获取要点击的按钮 12 ActionChains(driver).move_to_element(fl).click(dis1).perform() # 链式编程,可以一直点下去
1 from selenium.webdriver.common.action_chains import ActionChains 2 from selenium import webdriver 3 import time 4 driver = webdriver.Chrome() 5 driver.maximize_window() 6 driver.get('http://ui.imdsx.cn/uitester/') 7 time.sleep(2) 8 driver.execute_script('window.scrollTo(0,0);') 9 time.sleep(1) 10 a = driver.find_element_by_id('a').location # 获取元素坐标,返回的是一个字典 11 # {'x': 716, 'y': 112} 12 dis = driver.find_element_by_id('dis1') 13 ActionChains(driver).move_by_offset(a['x'],a['y']).double_click(dis).perform()
实际上ActionChains这个模块的实现的核心思想就是,当你调用ActionChains的方法时,不会立即执行,而是会将所有的操作按顺序存放在一个List里,当你调用perform()方法时,队列中的时间会依次执行。
drag_and_drop
1 # 将source元素拖放至target元素处,参数为两个elementObj 2 ActionChains(driver).drag_and_drop(source=source, target=target) 3 4 # 将一个source元素 拖动到针对source坐上角坐在的x y处 可存在负宽度的情况和负高度的情况 5 ActionChains(driver).drag_and_drop_by_offset(source, x, y) 6 7 # 这种也是拖拽的一种方式,都是以源元素的左上角为基准,移动坐标 8 ActionChains(driver).click_and_hold(dom).move_by_offset(169, 188).release().perform() 9 10 例子: 11 # 拼图,拖动图片到指定位置 12 from selenium.webdriver.common.action_chains import ActionChains 13 gl = driver.find_element_by_css_selector('[href="/move/"]') 14 gl.click() 15 handes = driver.window_handles 16 driver.switch_to.window(handes[1]) 17 source = driver.find_element_by_css_selector('#dragger') 18 target = driver.find_element_by_css_selector('#i1') 19 source1 = driver.find_element_by_css_selector('#dragger1') 20 target1 = driver.find_element_by_css_selector('#i2') 21 source2 = driver.find_element_by_css_selector('#dragger2') 22 target2 = driver.find_element_by_css_selector('#i3') 23 source3 = driver.find_element_by_css_selector('#dragger3') 24 target3 = driver.find_element_by_css_selector('#i4') 25 # drag_and_drop 拖拽 26 ActionChains(driver).drag_and_drop(source,target).drag_and_drop(source1,target1).drag_and_drop(source2,target2).drag_and_drop(source3,target3).perform()
click
1 # 单击事件,可接受elementObj 2 ActionChains(driver).click() 3 4 # 双击事件,可接受elementObj 5 ActionChains(driver).double_click() 6 7 # 点击鼠标右键 8 ActionChains(driver).context_click() 9 10 # 点击某个元素不松开,接收elementObj 11 ActionChains(driver).click_and_hold() 12 13 # # 某个元素上松开鼠标左键,接收elementObj 14 ActionChains(driver).release()
key_up与key_down
有时我们需要模拟键盘操作时,那么就需要用到ActionChains中的key操作了,提供了两个方法,key_down与key_up,模拟按下键盘的某个键子,与松开某个键子,接收的参数是按键的Keys与elementObj。可以与send_keys连用(例:全选、复制、剪切、粘贴)
1 # key_down 模拟键盘摁下某个按键 key_up 松开某个按键,与sendkey连用完成一些操作,每次down必须up一次否则将出现异常 2 ActionChains(driver).key_down(Keys.CONTROL,dom).send_keys('a').send_keys('c').key_up(Keys.CONTROL)\ 3 .key_down(Keys.CONTROL,dom1).send_keys('v').key_up(Keys.CONTROL).perform()
Keys 实际是Selenium提供的一个键盘事件模块,在模拟键盘事件时需要导入Keys模块
引入方式
1 from selenium.webdriver.common.keys import Keys
Switch与SelectApi接口详解
我们在UI自动化测试时,总会出现新建一个tab页面、弹出一个浏览器级别的弹框或者是出现一个iframe标签,这时我们用WebDriver提供的Api接口就无法处理这些情况了。需要用到Selenium单独提供的模块switch_to模块
SwitchToWindows
1 handles = driver.window_handles 2 3 # SwitchToWindows接受浏览器TAB的句柄 4 driver.switch_to.window(handles[1])
例子:
1 # 浏览器句柄及指针切换 2 print(driver.window_handles) # 获取所有打开server的浏览器句柄,返回的是一个list 3 bl = driver.find_element_by_css_selector('[href="/new-index/"]') 4 bl.click() # 点击连接打开一个新的页面 5 print(driver.window_handles) # 再次获取所有打开server的浏览器句柄 6 handes = driver.window_handles 7 driver.switch_to.window(handes[1]) # 切换浏览器句柄到新打开的这个页面 8 cl = driver.find_element_by_css_selector('#newtag') 9 cl.send_keys('AAAA') 10 driver.close() # 关闭当前指针指向句柄的页面 11 driver.switch_to.window(handes[0]) # 手动将浏览器指针切换回之前的页面 12 driver.find_element_by_css_selector('#i1').send_keys('EEEE') 13 driver.quit() # 关闭所有页面
SwitchToFrame
1 # SwitchToFrame支持id、name、frame的element 2 3 # 接受定位到的iframe的Element,这样就可以通过任意一种定位方式进行定位了 4 frameElement = driver.find_element_by_name('top-frame') 5 driver.switch_to.frame(frameElement) 6 7 # 通过fame的name、id属性定位 8 driver.switch_to.frame('top-frame') 9 10 # 当存在多层iframe嵌套时,需要一层一层的切换查找,否则将无法找到 11 driver.switch_to.frame('top-frame') 12 driver.switch_to.frame('baidu-frame') 13 14 # 跳转到最外层的页面 15 driver.switch_to.default_content() 16 17 # 多层Iframe时,跳转到上一层的iframe中 18 driver.switch_to.parent_frame()
例子:
1 # 多层iframe切换,需要一层一层进入,但是能从任意一层切换到最外层 2 # 切换到top-frame 3 driver.switch_to.frame('top-frame') 4 import time 5 time.sleep(1) 6 # 输入newtag文案 7 driver.find_element_by_css_selector('#newtag').send_keys('XXXX') 8 # 切换到baidu-frame 9 driver.switch_to.frame('baidu-frame') 10 time.sleep(1) 11 # 输入kw文案 12 driver.find_element_by_css_selector('#kw').send_keys('YYYY') 13 # 返回上一层frame,即top-frame 14 driver.switch_to.parent_frame() 15 # 清空top-frame的输入 16 driver.find_element_by_css_selector('#newtag').clear() 17 # 再切换到baidu-frame 18 driver.switch_to.frame('baidu-frame') 19 # 再清空baidu-frame的输入 20 driver.find_element_by_css_selector('#kw').clear() 21 # 切换到最外层frame 22 driver.switch_to.default_content() 23 # 输入i1文案 24 driver.find_element_by_css_selector('#i1').send_keys('NNNN')
SwitchToAlert
1 # alert 实际上也是Selenium的一个模块 2 from selenium.webdriver.common.alert import Alert 3 4 # 也可以通过Webdriver的switch_to来调用 5 6 # 点击确认按钮 7 driver.switch_to.alert.accept() 8 9 # 如果是确认弹框,相当于点击需要和X按钮 10 driver.switch_to.alert.dismiss() 11 12 13 # 如果alert上有文本框时,可以输入文字。(注: 没遇到过) 14 driver.switch_to.alert.send_keys() 15 16 # 返回Alert上面的文本内容 17 text = driver.switch_to.alert.text
例子:
1 # 弹框处理 2 driver.find_element_by_css_selector('#confirm').click() # 点击按钮,弹出弹框 3 print(driver.switch_to.alert.text) # 打印弹框返回的文本文字 4 driver.switch_to.alert.accept() # 确认 5 driver.switch_to.alert.dismiss() # 取消
Select
在UI自动化测试过程中,经常会遇到一些下拉框,如果我们基于Webdriver操作的话就需要click两次,而且很容易出现问题,实际上Selenium给我们提供了专门的Select(下拉框处理模块)。
1 # 通过select选项的索引来定位选择对应选项(从0开始计数) 2 Select(s).select_by_index(5) 3 4 # 通过选项的value属性值来定位 5 Select(s).select_by_value('2') 6 7 # 通过选项的文本内容来定位 8 Select(s).select_by_visible_text('牡丹江') 9 10 # 返回第一个选中的optionElement对象 11 Select(s).first_selected_option 12 13 # 返回所有选中的optionElement对象 14 Select(s).all_selected_options 15 16 # 取消所有选中的option 17 Select(s).deselect_all() 18 19 # 通过option的index来取消对应的option 20 Select(s).deselect_by_index(1) 21 22 # 通过value属性,来取消对应option 23 Select(s).deselect_by_value('') 24 25 # 通过option的文本内容,取消对应的option 26 Select(s).deselect_by_visible_text('')
例子:
1 # 点击下拉菜单再点击一个值 2 from selenium.webdriver.support.select import Select 3 driver.get('http://ui.imdsx.cn/html/') 4 driver.execute_script('window.scrollTo(0,1500);') 5 select = driver.find_element_by_xpath('//select[1]') 6 # 实例化select,接收一个select标签,如果不是select标签则抛异常 7 Select(select).select_by_value('2') # 通过select标签的option中的value的值定位 8 Select(select).select_by_index('2') # 通过select标签的option中的下标定位,从0开始
如果一个标签下还有子集,可以继续在这个标签小查找,如下:
1 driver.get('http://ui.imdsx.cn/html/') 2 driver.execute_script('window.scrollTo(0,1500);') 3 select = driver.find_element_by_xpath('//select[1]') 4 # 获取select标签下所有的option的元素 5 options = select.find_elements_by_tag_name('option') 6 for opt in options: 7 print(opt.get_attribute('value')) # 循环获取select('//select[1]')标签下的option的value属性 8 print(opt.get_attribute('index')) # 循环获取select('//select[1]')标签下的option的下标
二次开发
1 #!/usr/bin/env python 2 # encoding: utf-8 3 import unittest 4 5 import json 6 from selenium.webdriver.common.keys import Keys 7 from selenium.webdriver.support.select import Select 8 from uitester.common.logger import * 9 from selenium import webdriver 10 from selenium.webdriver.support.wait import WebDriverWait 11 from selenium.webdriver.common.by import By 12 from selenium.webdriver.chrome.options import Options 13 from selenium.webdriver import ActionChains 14 from selenium.webdriver.support import expected_conditions as EC 15 from selenium.common.exceptions import * 16 17 18 class BasePage(object): 19 # Page基类,所有其他Page全部继承此类,负责元素和driver方法的封装 20 def __init__(self, driver): 21 self.driver = driver 22 self.mgr_info = {} 23 self.agent_info = {} 24 self.read_config() 25 self.mgr_version = self.mgr_info.get('stable_platform_ver', '') 26 mgr_version_split = self.mgr_version.split('.') 27 # 方便版本比较, e.g. 3216 28 self.mgr_version_format = int(mgr_version_split[0] + mgr_version_split[1] + mgr_version_split[2][:2]) 29 30 def read_config(self): 31 # 方便适配版本 32 # uitester会以包的形式被引用 33 # config_path = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))), 'config.json')) 34 for name in os.listdir("C:\\jenkins\\workspace\\"): 35 if 'agent_' in name: 36 agent_name = name 37 break 38 config_path = os.path.join(r'C:\Jenkins\workspace\{}'.format(agent_name), 'config.json') 39 if os.path.exists(config_path): 40 with open(config_path) as f: 41 config_content = eval(f.read()) 42 config_content = json.loads(json.dumps(config_content)) 43 self.mgr_info = config_content['mgr_cfg'] 44 self.agent_info = config_content['agent_cfg'] 45 else: 46 LOG_DEBUG('配置文件config.json不存在!') 47 48 def find_element(self, loc, strict=False, timeout=10): 49 """ 50 51 :param loc: 52 :param strict: type: bool e.g.True:若找不到元素直接抛错 , False:若找不到元素,日志打印报错,不抛错 53 :return: 54 """ 55 try: 56 WebDriverWait(self.driver, timeout, 0.5).until(EC.presence_of_element_located(loc)) 57 except Exception as e: 58 LOG_DEBUG('[1] 页面未找到元素, loc: {}'.format(loc)) 59 try: 60 WebDriverWait(self.driver, timeout, 0.5).until(EC.visibility_of_element_located(loc)) 61 return self.driver.find_element(*loc) 62 except Exception as e: 63 LOG_DEBUG('[1] ERROR [find_element]: {}'.format(e)) 64 LOG_DEBUG('[1] 页面未找到元素, loc: {}'.format(loc)) 65 self.refresh() 66 time.sleep(8) 67 try: 68 WebDriverWait(self.driver, timeout, 0.5).until(EC.presence_of_element_located(loc)) 69 except Exception as e: 70 LOG_DEBUG('[2] 页面未找到元素, loc: {}'.format(loc)) 71 try: 72 WebDriverWait(self.driver, timeout, 0.5).until(EC.visibility_of_element_located(loc)) 73 return self.driver.find_element(*loc) 74 except Exception as e: 75 LOG_DEBUG('[2] ERROR [find_element]: {}'.format(e)) 76 LOG_DEBUG('[2] 页面未找到元素, loc: {}'.format(loc)) 77 if strict: 78 raise e 79 80 def find_elements(self, loc, strict=False, timeout=10): 81 try: 82 WebDriverWait(self.driver, timeout, 0.5).until(EC.presence_of_element_located(loc)) 83 except Exception as e: 84 LOG_DEBUG('ERROR [find_element]: {}'.format(e)) 85 LOG_DEBUG('页面未找到元素: {}'.format(loc)) 86 try: 87 WebDriverWait(self.driver, timeout, 0.5).until(EC.visibility_of_element_located(loc)) 88 return self.driver.find_elements(*loc) 89 except Exception as e: 90 LOG_DEBUG('ERROR [find_elements]: {}'.format(e)) 91 LOG_DEBUG('页面未找到元素: {}'.format(loc)) 92 if strict: 93 raise e 94 95 def clear(self, loc=None, ele=None, strict=False): 96 if not (loc or ele): 97 LOG_ERROR('loc: {}, ele: {}, 请至少输入一个有效参数!'.format(loc,