为什么要二次封装?
- 对一些常用的方法进行二次封装
- 简化用例的代码
步骤 1:driver 的初始化
- 定义了 extend 这个 class 作为对 selenium 常用方法的二次封装
- 初始化了类的属性 driver: 如果 driver 不存在,则通过 selenium webdriver 进行初始化; 如果已经被初始化过,则直接返回
- 在 init driver 的方法中,可以将你常用的 webdriver 启动方式加在里面。比如使用指定的浏览器类型或 webdriver 的路径; 是否使用 headless 模式运行; 是否使用远程的 selenium server 执行; 是否需要指定为 chrome 的模拟手机功能; 是否需要默认最大化。等等。
from selenium import webdriver
class extend():
"""
You can add new function here for you own.
"""
def __init__(self):
self.driver = self.init_driver()
def init_driver(self):
global driver
if driver is None:
print('======initial driver=====')
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(chrome_options=chromeOptions,desired_capabilities=chromeOptions.to_capabilities())
driver.maximize_window()
return driver
步骤 2: 封装一个自己通用的查找元素方式
在 selenium 执行 UI 自动化测试的过程中,会经常遇到以下问题:
- 某个元素没找到导致执行失败。需要加入失败重试机制。
- 不同的元素定位方式需要使用不同的方法。如果要换定位方式,需要修改对应的代码。
基于这些问题,我先封装一个通用的查找元素方法如下:
- 参考 robot framework selenium library 的方式,以 locator 的方式来定位元素(格式为 attribute=value)
- 返回一个 elements 的数组,并在其他的方法中扩展使用。
- 增加一些扩展的查找元素方式,比如 is displayed 设置为 false, 则可以将隐藏的元素也找出来; 如果传入 text 的值,则会在元素中过滤出包含该文本的元素。等。
def find_elements(self,driver,locator,is_displayed=True,text=''):
"""
Find elements using the given condition..
:param driver:
:param locator: like id=btn_search
:param is_displayed: True : Only the elements shown on the page will be returned. False: Elements will also be returned no matter is shown or hidden.
:param text: Only the elements contain the specified text will be returned.
:return: Found element list.
"""
method, value = locator.split('=',maxsplit=1)
if 'css' in method:
method = By.CSS_SELECTOR
elif 'class' in method:
method = By.CLASS_NAME
elif 'text' in method:
method = By.PARTIAL_LINK_TEXT
elif 'tag' in method:
method = By.TAG_NAME
elements = driver.find_elements(by=method,value=value)
new_elements = []
for element in elements:
if text != '':
if self.is_text_in_element(element,text):
if is_displayed:
if element.is_displayed():
new_elements.append(element)
else:
new_elements.append(element)
else:
if is_displayed:
if element.is_displayed():
new_elements.append(element)
else:
new_elements.append(element)
return new_elements
def find_element(self,driver,locator,is_displayed=True,index=0,text=''):
"""
Find element using the given condition..
:param driver:
:param para_list: [method, value] eg : ['id','add_btn']
:param is_displayed: True : Only the element shown on the page will be returned. False: Element will also be returned no matter is shown or hidden.
:param index: If more than one element is found, driver will return the specified element by index. e.g: element 0,1,2 is found and the index is set to by 2, the element 2 will be returned.
:param text: Only the element contains the specified text will be returned.
:return: Found element.
"""
elements = self.find_elements(driver,locator,is_displayed=is_displayed,text=text)
if len(elements)>0 and index < len(elements):
return elements[index]
else:
return elements[0]
步骤 3: 扩展
扩展常用的操作步骤:
- click: 点击元素。 如果有多个符合条件的元素,还可以指定要点击第几个。 使用例子: click_index('class=btn',index=1) # 点击第 2 个 class 为 btn 的按钮
def click_index(self,driver,locator,index=0):
"""
When more than one web element are found by the given value, you can use the index the specified which element you want to click.
:param driver:
:param index: default to 0, means to click the first element found.
:return:
"""
elements = self.find_elements(driver, locator)
elements[int(index)].click()
time.sleep(2)
- fill: 输入
例子:
fill('id=searchField',text='testerhome')
def fill(self,driver,locator,text, is_displayed = True,index=0):
"""
Fill specified text to the target web elelemnt.
:param driver:
:param para_list: [method, value]
:param text: the text you want to input
:param is_displayed:
:param index:
:return:
"""
text = self.replaceRandomValue(text)
elements = self.find_elements(driver, locator,is_displayed,text='')
elements[index].clear()
elements[index].send_keys(text)
- 点击文字: 例如一些通用的按钮或者菜单,可直接通过对于的文本来点击,无需关心 id、xpath 等属性。 简化用例的编写。
def click_text(self,driver,text,type=''):
"""
click a web element by it's text and type.
:param driver:
:param text:
:param type: by default is empty. you can specified the type to it's tag name. e.g : span, li, a .
:return:
"""
if len(type) ==0:
try :
driver.find_element_by_link_text(text).click()
except:
try:
driver.find_element_by_partial_link_text(text).click()
except:
elements = driver.find_elements(by='xpath', value="//*[contains(.,'" + text + "')]")
for element in elements:
element.click()
else:
elements = self.find_elements(driver, ['tag', type], is_displayed=True, text=text)
if len(elements):
elements[0].click()
time.sleep(2)
- 尝试点击某元素: 适用于某些偶然条件下出来的按钮或者窗口
def try_click(self,driver,locator):
"""
Try to click on a specified web element. Sometimes a message will be popped up on a web page. We need this function to close the pop up window.
:param driver:
:param para_list:
:return:
"""
for i in range(3):
try:
self.find_element(driver, locator).click()
break
except:
pass
time.sleep(2)
- 滚动页面到底部; 滚动页面到某个元素 例如某个页面较长,可以通过这个方法滚动到对于的按钮后再进行操作; 甚至可以将其内置到 点击、填写等操作类方法中,解决元素不在当前可见区域时无法操作的问题。
def scroll_down(self,height=0):
if height:
self.driver.execute_script('window.scrollTo(0,%s)' %height)
else:
self.driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
def scroll_to_element(self,locator):
for i in range(1,50):
height = i*200
self.driver.execute_script('window.scrollTo(0,%s)' % height)
self.wait(1)
if len(self.find_elements(locator)):
break
如何使用:
from app.core.extend import extend
new_driver = extend() # 初始化自己封装的driver 库
new_driver.driver.get('https://www.baidu.com') # 仍可以通过 .driver 来调用原来 selenium 的driver 方法
new_driver.fill('id=kw','testerhome')
new_driver.click_index('id=su')
转载文章时务必注明原作者及原始链接,并注明「发表于 TesterHome 」,并不得对作品进行修改。
暂无回复。