[Selenium][Notes]Day3:5️⃣三种等待方式

259 阅读4分钟
Background:

UI自动化过程中,必然会遇到环境不稳定,网络慢情况,加载问题,如果不做任何处理就会因为没有找到元素而报错。另外一种情况就是页面使用了ajax异步加载机制(现在都是resetful,客户端和服务端都是分离的),不知道页面是什么时候到达的。这时我们就要用到wait,而在selenium中,我们一共又三种等待。

1.time.sleep(固定等待)
  • 本质:让当前的线程睡眠,实质是线程的阻塞(blocking),用wait方式实现。
  • 缺点:网络条件好浪费时间,严重影响项目的性能
  • 好处:调试脚本可以用
2.implicitly_wait(隐式等待)
  • 本质:在脚本的开始设置一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步;否则可能抛出异常。隐式等待对整个driver周期都起作用,在最开始设置一次就可以了,不要当作固定等待使用。
  • 缺点:Javascript一般都是放在我们的body的最后进行加载,实际这时页面的元素都已经加载完毕,我们却还在等待全部页面加载结束。
3.WebDriverWait(显式等待)
  • 本质:动态的等待,判断某一个元素是不是已经出现了,比如title是不是叫百度或百度搜索,根据动态的一些条件来轮询,它会不停的轮询去给我们检测,条件是成功还是失败,比如0.5s就检测一次这个元素在这个条件下是成功还是失败。同时设置轮询的超时时间。

  • WebDriverWait是Selenium提供得到显示等待模块引入路径

  • 引入方式: from selenium.webdriver.support.wait import WebdriveWait

  • WebdriveWait参数 | # | 参数 | 参数说明 | | --- | --- | --- | | 1 | driver | 传入WebDriver实例 | | 2 | timeout | 超出时间,等待的最长时间 | | 3 | poll_frequency | 调用until或until_not中的方法的间隔时间,默认是0.5s | | 4 | ignored_exceptions | 忽略的异常 |

  • 两种方法 untiluntil_not:

    • until()调用该方法提供的驱动作为一个参数,直到返回值为True;
    • unitl_not()调用该方法提供的驱动作为一个参数,直到返回值为False | # | 参数 | 参数说明 | | --- | --- | --- | | 1 | method | 在等待期间,每隔一段时间用这个传入的方法,直到返回值不是false | | 2 | message | 如果超时,抛出Timeoutexception,将message传入异常 |
  • 注意事项

  • WebDriverWait的方法要传入几个参数,第一个是传入WebDriver的实例:driver,第二个是传入超时时间,timeout,就是比如传入3秒,3秒还没有成功就跑出超时异常
  • 如果既设置了隐式等待也设置了显式等待,那么程序会根据谁设置的超时时间越长来按照它的执行

特别注意的是untiluntil_not中的可执行方法method参数,不能传入了WebElement对象,如下:

# 错误
WebDriverWait(self.driver, 3).until(self.driver.find_element_by_id('kw'))

这是错误的用法,这里的参数一定要是可以调用的,即这个对象一定有_ _call__()方法,否则会抛出异常: TypeError: 'xxx' object is not callable。可以用Selenium提供的expected_conditions模块中的各种条件,也可以用WebElement的is_displayed()is_enabled()is_selected()方法,或者用自己封装的方法。

显式等待和隐式等待的区别:

隐式等待只需设置一次,后面都会生效。显式等待根据条件设置,条件成立就执行,条件不成立就继续等待,如果到达时间了就会跑出timeout异常。

实例Code:
from selenium import webdriver
from time import sleep
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

class TestCase(object):
    def __init__(self):
        self.driver = webdriver.Chrome()
        self.driver.get('http://www.baidu.com')

    # time.sleep(固定等待)
    def test_sleep(self):
        self.driver.find_element_by_id('kw').send_keys('Selenium')
        # 线程阻塞 blocking wait 2s
        sleep(2)
        self.driver.find_element_by_id('su').click()
        sleep(2)
        self.driver.quit()

    # implicitly_wait(隐形等待)
    def test_implicitly(self):
        # 全局最长等待10s
        self.driver.implicitly_wait(10)
        self.driver.find_element_by_id('kw').send_keys('Selenium')
        self.driver.find_element_by_id('su').click()
        self.driver.quit()

    # WebDriverWait(显性等待)
    def test_wait(self):
        # 1.传入WebDriverWait的实例 2.传入超时时间,timeout
        wait = WebDriverWait(self.driver, 2)
        # 等待页面标题加载成功
        wait.until(EC.title_is('百度一下,你就知道'))
        # 传入driver参数,然后超时时间为2秒,再调用until方法,去获取标题是不是和设置的一样,如果是返回true,执行下一步,如果不是,就继续请求,每0.5秒请求一次,2秒结束后还没有成功,就抛出超时异常

        self.driver.find_element_by_id('kw').send_keys('Selenium')
        self.driver.find_element_by_id('su').click()
        self.driver.quit()

if __name__ == '__main__':
    case = TestCase()
    # case.test_sleep()
    # case.test_implicitly()
    case.test_wait()