【UI自动化】selenium中三种等待方式

Selenium 等待方式

  • Selenium 等待方式[^示例]
    • time.sleep(seconds) 固定等待
    • 智能隐性的等待implicitly_wait(回应超时等待)
    • 智能显性等待WebDriverWait
  • expected_conditions 类库


time.sleep(3) 固定等待3秒

driver.implicitly_wait(10) 隐性的等待,对应全局

WebDriverWait( driver, timeout).until(‘有返回值的__call__()方法或函数’) 显性的等待,对应到元素


Selenium 等待方式1

time.sleep(seconds) 固定等待

import time

time.sleep(3)  # 等待3秒

time.sleep(seconds) seconds参数为整数,单位(秒)。

它是Python的time提供的休眠方法。

常用于短时间的等待,为了自动测试用例的执行效率固定等待的时间需要控制在3秒内。在用例中尽量少用固定等待。


智能隐性的等待implicitly_wait(回应超时等待)

driver.implicitly_wait(time_to_wait)

回应超时等待,隐性的,设置后对应的是全局,如查找元素。

driver.implicitly_wait(10) # 设置全局隐性等待时间,单位秒
每次driver执行 找不到元素都会等待设置的时间,它的值设置的过长对用例执行效率有很大的影响,必须在执行完成之后还原回来。driver.implicitly_wait() 要慎之又慎的使用。

driver对它的默认值为0,driver.implicitly_wait(0)能还原隐性等待的设置时间。

智能显性等待WebDriverWait

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

参数说明:
driver 为webdriver驱动
timeout 最长超时时间,单位(秒)
poll_frequency 循环查找元素每次间隔的时间,默认0.5秒
ignored_exceptions 超时后需要输出的异常信息

WebDriverWait()下面有两个方法可用until()和until_not()

WebDriverWait(driver, timeout).until(method, message=‘’)

method 函数或者实例__call__()方法返回True时停止,否则超时后抛出异常。

参数说明:
method 在等待时间内调用的方法或者函数,该方法或函数需要有返回值,并且只接收一个参数driver。
message 超时时抛出TimeoutException,将message传入异常显示出来

WebDriverWait(driver, timeout).until_not(method, message='')

于上面的until() 相反,until_not 中的method函数或者实例__call__()方法返回False结束,否则抛出异常。

until方法使用的method 的函数或者类__call()__方法详解:

函数我们一般采用匿名函数lambda 。

lambda driver:driver.find_element(<定位元素>) # 当定位的元素时为True,无元素时为False。如示例1、2:

WebDriverWait示例1:

WebDriverWait(driver, 5).until(lambda driver: driver.find_element_by_id('query'))
'''5秒内等待元素(id='query')出现,
lambda driver:driver.find_element_by_id('query') 为一个匿名函数,只有一个driver参数,返回的是查找的元素对象。'''

WebDriverWait示例2:

WebDriverWait(driver, 5).until_not(lambda driver: driver.find_element_by_name('query'))
'''5秒内等待元素消失,同示例1 until_not 要求无元素返回即元素不存在于该页面。'''

定义类中的__call()__方法。

class wait_element(object):
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        return driver.find_element(self.locator)

        WebDriverWait(driver, 5).until(wait_element((By.ID, 'query')))  # 等待元素出现
        WebDriverWait(driver, 5).until_not(wait_element((By.ID, 'query')))  # 等待元素消失

wait_element类中__init__()方法接收需要定位的元素,call()方法中只能有唯一变量driver,并且返回元素对象。

这样做是是不是很麻烦,其实selenium提供的一个库进行操作,expected_conditions库。引入位置

from selenium.webdriver.support import expected_conditions as ec,它囊括了我们需要使用等待的所有情况。

expected_conditions 类库

方法 说明
title_is 判断当前页面的 title 是否完全等于(==)预期字符串,返回布尔值
title_contains 判断当前页面的 title 是否包含预期字符串,返回布尔值
presence_of_element_located 判断元素是否被加到了 dom 树里(注意,加载到dom树中,并不代表这个元素可见)
visibility_of_element_located 判断元素是否可见
visibility_of 同visibility_of_element_located方法,只是visibility_of_element_located方法参数为locator,这个方法参数是 定位后的元素
presence_of_all_elements_located 判断是否至少有 1 个元素存在于 dom 树中。举例:如果页面上有 n 个元素的 class 都是’wp’,那么只要有 1 个元素存在,这个方法就返回 True
text_to_be_present_in_element 判断某个元素中的 text 是否 包含 了预期的字符串
text_to_be_present_in_element_value 判断某个元素中的 value 属性是否包含 了预期的字符串
frame_to_be_available_and_switch_to_it 判断该 frame 是否可以 switch进去,如果可以的话,返回 True 并且 switch 进去,否则返回 False
invisibility_of_element_located 判断某个元素中是否不存在于dom树或不可见
element_to_be_clickable 判断某个元素中是否可见并且可点击
staleness_of 等某个元素从 dom 树中移除,注意,这个方法也是返回 True或 False
element_to_be_selected 判断某个元素是否被选中了,一般用在下拉列表
element_selection_state_to_be 判断某个元素的选中状态是否符合预期
element_located_selection_state_to_be 跟上面的方法作用一样,只是上面的方法传入定位到的 element,而这个方法传入 locator
alert_is_present 判断页面上是否存在 alert

from selenium.webdriver.support import expected_conditions as ec # 引入包
下面示例都是以搜狗搜索首页为例。

方法中参数说明 locator=(By.ID, ‘id’) 表示使用By方法定位元素的元组,element表示获取的webElement元素对象。

  • ec.title_is(‘title’) 判断页面标题等于title

  • ec.title_contains(‘title’) 判断页面标题包含title

    WebDriverWait(driver, 10).until(ec.title_is('搜狗搜索引擎 - 上网从搜狗开始'))  # 等待title 于参数相等
    WebDriverWait(driver, 10).until(ec.title_contains('搜狗搜索引擎'))  # 等待title 包含 参数的内容
    
  • ec.presence_of_element_located(locator) 等待locator元素是否出现

  • ec.presence_of_all_elements_located(locator) 等待所有locator元素是否出现

    WebDriverWait(driver, 10).until(ec.presence_of_element_located((By.ID, 'query')))
    WebDriverWait(driver, 10).until(ec.presence_of_all_elements_located((By.ID, 'query')))
    
  • ec.visibility_of_element_located(locator) 等待locator元素可见

  • ec.invisibility_of_element_located(locator) 等待locator元素隐藏

  • ec.visibility_of(element) 等待element元素可见

    WebDriverWait(driver, 10).until(ec.visibility_of_element_located((By.ID, ''stb'')))  # 等待元素可见
    WebDriverWait(driver, 10).until(ec.invisibility_of_element_located((By.ID, ''stb'')))  # 等待元素隐藏
    WebDriverWait(driver, 10).until(ec.visibility_of(driver.find_element_by_link_text('高级搜索')))  # 等待元素可见
    
  • ec.text_to_be_present_in_element(locator,text) 等待locator的元素中包含text文本

  • ec.text_to_be_present_in_element_value(locator,value) 等待locator元素的value属性为value

    WebDriverWait(driver, 10).until(ec.text_to_be_present_in_element((By.ID, 'erwx'), '搜索APP'))  # 等待元素中包含搜索APP文本
    WebDriverWait(driver, 10).until(ec.text_to_be_present_in_element_value((By.ID, 'query'),'selenium'))  # 等待元素的值为 selenium,一般用于输入框
    
  • ec.frame_to_be_available_and_switch_to_it(locator) 等待frame可切入

    WebDriverWait(driver, 10).until(ec.frame_to_be_available_and_switch_to_it((By.ID, 'frame')))
    WebDriverWait(driver, 10).until(ec.frame_to_be_available_and_switch_to_it('frameid'))
    
  • ec.alert_is_present() 等待alert弹出窗口出现

    WebDriverWait(driver, 10).until(ec.alert_is_present())
    
  • ec.element_to_be_clickable(locator) 等待locator元素可点击

  • WebDriverWait(driver, 10).until(ec.element_to_be_clickable((By.ID, 'kw')))
    等待元素被选中,一般用于复选框,单选框

  • ec.element_to_be_selected(element) 等待element元素是被选中

  • ec.element_located_to_be_selected(locator) 等待locator元素是被选中ec.element_selection_state_to_be(element, is_selected)
    等待element元素的值被选中为is_selected(布尔值)

  • ec.element_located_selection_state_to_be(locator,is_selected) 等待locator元素的值是否被选中is_selected(布尔值)

    from selenium import webdriver
    import time
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as ec  # 引入包
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    driver.maximize_window() 
    driver.get(r'https://www.baidu.com/') 
    driver.find_element_by_link_text('设置').click()
    WebDriverWait(driver, 3).until(ec.element_to_be_clickable((By.LINK_TEXT, '搜索设置')))  # 等待搜索可点击,不可缺少
    driver.find_element_by_link_text('搜索设置').click()
    element = driver.find_element_by_id('s1_1')
    WebDriverWait(driver, 2).until(ec.element_to_be_selected(element))  # element被选中
    WebDriverWait(driver, 10).until(ec.element_located_to_be_selected((By.ID, 'SL_0'))) # id=’SL_0’ 被选中
    WebDriverWait(driver, 10).until(ec.element_selection_state_to_be(element,True )) # element 被选中
    WebDriverWait(driver, 10).until(ec.element_located_selection_state_to_be((By.ID, 'SL_1'), False)) #  id=’SL_1’不被选中
    time.sleep(3)
    driver.quit()
    
  1. 什么时候使用等待
    固定等待sleep与隐性等待implicitly_wait尽量少用,它会对测试用例的执行效率有影响。

    显性的等待WebDriverWait可以灵活运用,什么时候需要用到?

    1、页面加载的时候,确认页面元素是否加载成功可以使用WebDriverWait

    2、页面跳转的时候,等待跳转页面的元素出现,需要选一个在跳转前的页面不存在的元素

    3、下拉菜单的时候,如上百度搜索设置的下拉菜单,需要加上个时间断的等待元素可点击

    4、页面刷新的时候

    总之,页面存在改变的时候;页面上本来没的元素,然后再出现的元素


  1. from selenium import webdriver
    # 导入sleep
    from time import sleep
    
    from selenium.webdriver.common.by import By
    
    
    def run_sleep():
        # 创建谷歌浏览器对象
        chrome_driver = webdriver.Chrome()
        # 访问百度
        chrome_driver.get("http://www.baidu.com")
        # 定位登录按钮并进行点击
        chrome_driver.find_element(By.XPATH, '//*[@id="s-top-loginbtn"]').click()
        # 设置等待时间,单位是秒
        print('this is sleep')
        sleep(3)
        chrome_driver.quit()
    
    
    def run_implicitly_wait():
        # 创建谷歌浏览器对象
        chrome_driver = webdriver.Chrome()
        # 智能等待,在设置时间范围内,只要条件成立,马上结束等待, implicitly_wait
        chrome_driver.implicitly_wait(5)
        # 访问百度
        chrome_driver.get("http://www.baidu.com")
        # 定位登录按钮并进行点击,在5s之内,找到元素,会立即点击
        print('5s内 找到并点击')
        chrome_driver.find_element(By.XPATH, '//*[@id="s-top-loginbtn"]').click()
        print('5s内 未找到')
        # 设置一个找不到的元素,会进行等待,等待5s后,依旧找不带,会抛出异常
        chrome_driver.find_element(By.XPATH, '//*[@id="s-top-loginbtn1"]').click()
    
    
    def run_webdriver_wait():
        from selenium.webdriver.support.wait import WebDriverWait
        from selenium.webdriver.support import expected_conditions as ec
        from selenium.webdriver.common.by import By
        # 创建谷歌浏览器对象
        chrome_driver = webdriver.Chrome()
        # 使用显性等待, 等待元素id="TANGRAM__PSP_11__changeSmsCodeItem"加载到dom树中,等待上限是10s,每0.8秒去验证一下条件是否成立.
        WebDriverWait(chrome_driver, 10, 0.8).until(ec.presence_of_element_located((By.ID,
                                                                                    'TANGRAM__PSP_11__changeSmsCodeItem')))
    
    
    print('Selenium 等待方式')
    print('==> sleep')
    run_sleep()
    print('==> 显式等待')
    run_implicitly_wait()
    print('==> 隐式等待')
    run_webdriver_wait()
    
    ↩︎

你可能感兴趣的:(Python,自动化,selenium,python)