1127UI自动化测试经验分享-显式等待(一)WebDriverWait类、until()方法

2023-05-16

最近忙于其他事情,博客就没那么多时间来写。原本想先分享下三种等待方式,但是隐式等待我还有点不太懂。这次先分享显式等待。

个人博客:https://blog.csdn.net/zyooooxie

一)显式等待 WebDriverWait()

显示等待,是针对于某个特定的元素设置的等待时间。

源码:

POLL_FREQUENCY = 0.5  # How long to sleep inbetween calls to the method
IGNORED_EXCEPTIONS = (NoSuchElementException,)  # exceptions ignored during calls to the method


class WebDriverWait(object):
    def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
        """Constructor, takes a WebDriver instance and timeout in seconds.

           :Args:
            - driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote)
            - timeout - Number of seconds before timing out
            - poll_frequency - sleep interval between calls
              By default, it is 0.5 second.
            - ignored_exceptions - iterable structure of exception classes ignored during calls.
              By default, it contains NoSuchElementException only.

           Example:
            from selenium.webdriver.support.ui import WebDriverWait \n
            element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n
            is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n
                        until_not(lambda x: x.find_element_by_id("someId").is_displayed())
        """
        self._driver = driver
        self._timeout = timeout
        self._poll = poll_frequency
        # avoid the divide by zero
        if self._poll == 0:
            self._poll = POLL_FREQUENCY
        exceptions = list(IGNORED_EXCEPTIONS)
        if ignored_exceptions is not None:
            try:
                exceptions.extend(iter(ignored_exceptions))
            except TypeError:  # ignored_exceptions is not iterable
                exceptions.append(ignored_exceptions)
        self._ignored_exceptions = tuple(exceptions)

通过注释了解到:ignored_exceptions:调用方法时忽略的异常;poll_frequency:在调用方法之间睡多久;

init()方法需要传参 driver、timeout、poll_frequency、ignored_exceptions;
driver:webdriver的驱动;
timeout:最长超时时间,默认以秒为单位;
poll_frequency:休眠时间(步长)的间隔,检测间隔时间,默认0.5s;
ignored_exceptions: 超时后的异常信息,默认情况下抛 “NoSuchElementException"异常;

在设置时间timeout内,每隔一段时间poll_frequency(默认0.5秒) 检测一次当前页面,元素是否存在,如果超过设置时间还检测不到则抛出异常ignored_exceptions,如果元素存在则立即反馈。

那要怎么用呢?
看下官方的举例:element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id(“someId”))

is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).until_not(lambda x: x.find_element_by_id(“someId”).is_displayed())

二)until()、until_not()

WebDriverWait 一般是配合until() 或 until_not()方法,就能够根据判断条件而灵活地等待了。主要的意思就是:程序每隔xx秒看一眼,如果条件成立了,则执行下一步;否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException异常。

格式:
WebDriverWait(driver, timeout).until(method, message=’’)
WebDriverWait(driver, timeout).until_not(method, message=’’)

【until_not() 我没用过,本篇就分享until()】

源码:

    def until(self, method, message=''):
        """Calls the method provided with the driver as an argument until the \
        return value is not False."""
        screen = None
        stacktrace = None

        end_time = time.time() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if value:
                    return value
            except self._ignored_exceptions as exc:
                screen = getattr(exc, 'screen', None)
                stacktrace = getattr(exc, 'stacktrace', None)
            time.sleep(self._poll)
            if time.time() > end_time:
                break
        raise TimeoutException(message, screen, stacktrace)

    def until_not(self, method, message=''):
        """Calls the method provided with the driver as an argument until the \
        return value is False."""
        end_time = time.time() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if not value:
                    return value
            except self._ignored_exceptions:
                return True
            time.sleep(self._poll)
            if time.time() > end_time:
                break
        raise TimeoutException(message)

until(method,message=’’) 的注释:Calls the method provided with the driver as an argument until the return value is not False 将驱动提供的方法作为参数调用,直到返回值不为False;

好绕啊,要疯啦,
我觉得就是在说:调用method作为一个参数,直到返回值为True;

那这个参数(或者叫条件) value = method(self._driver) 到底是什么,要怎样用呢?

不妨回到起点,显式等待到底是什么?
显式等待会让WebDriver等待满足一定的条件以后再进一步的执行。 这 满足一定的条件 是不是value?我觉得 就是。

在自动化测试中,最基本的、最重要的 要满足的条件就是查找到元素,find element;
所以value 应该可以写成driver.find_element(),对吧?

    def test_56(self):
        """ 可执行方法method参数,很多人传入了WebElement对象 这是错误的"""
        from selenium.webdriver.support.wait import WebDriverWait

        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(5)
        self.driver.get("https://www.baidu.com")
        WebDriverWait(self.driver, 10).until(self.driver.find_element_by_id('kw'))  # 错误

        time.sleep(2)
        self.driver.quit()

但 报错了。

  File "D:\oss_1\Common\yidu.py", line 3900, in test_56
    WebDriverWait(self.driver, 10).until(self.driver.find_element_by_id('kw'))  # 错误
  File "C:\Users\admin\AppData\Local\Programs\Python\Python36-32\lib\site-packages\selenium\webdriver\support\wait.py", line 71, in until
    value = method(self._driver)
TypeError: 'WebElement' object is not callable

说的是 ‘WebElement’ object is not callable;所以 这里的参数一定要是可以调用的,即这个对象一定有 call() 方法,否则会抛出异常。

如何处理呢? 一般采用匿名函数lambda 。
lambda driver:driver.find_element(<定位元素>)
当定位到元素时返回为WebElement,找不到元素时为显式等待 报错】(这儿后面会继续深入分享)

    def test_57z3(self):
        from selenium.webdriver.support.wait import WebDriverWait

        driver = webdriver.Chrome()
        driver.maximize_window()
        driver.get("https://www.baidu.com")
        print('0', time.ctime())

        # TypeError: 'WebElement' object is not callable
        try:
            WebDriverWait(driver, 10).until(driver.find_element_by_id('kw'), '失败')
        except Exception as e11:
            print(e11)
        print('1', time.ctime())

        # 成功
        try:
            WebDriverWait(driver, 10).until(lambda the_driver: the_driver.find_element_by_id('kw'), '失败')
        except Exception as e33:
            print(e33)
        print('3', time.ctime())

        time.sleep(1)
        driver.quit()

这个用例就说明了 显式等待和until()结合后,可以智能查找元素;但是在web中有些元素是隐藏的,确实是存在;只不过不显示,那就不方便执行操作,要怎么做一个可以判断元素显示与否的显式等待呢?

用WebElement的 is_displayed() 、is_enabled()、is_selected() 方法
WebDriverWait(driver, 10).until(lambda the_driver: the_driver.find_element_by_id(‘kw’).is_displayed())

    def test_57z5(self):
        from selenium.webdriver.support.wait import WebDriverWait
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.get("https://www.12306.cn/index/")
        print('开始', time.ctime())

        # <input id="toStation" type="hidden" value="" name="to_station">
        # 这个元素默认是隐藏的

        # selenium.common.exceptions.TimeoutException: Message: 失败
        try:
            WebDriverWait(self.driver, 10).until(lambda the_driver: the_driver.find_element_by_id('toStation').is_displayed(), '失败')
        except Exception as e33:
            print(e33)  # 显式等待的10秒      Message: 失败
        print('0', time.ctime())

        # 成功
        try:
            WebDriverWait(self.driver, 10).until(lambda the_driver: the_driver.find_element_by_id('toStation'), '失败')
        except Exception as e33:
            print(e33)
        print('1', time.ctime())

        time.sleep(1)
        self.driver.quit()

结果很明显:

Launching unittests with arguments python -m unittest yidu.Test_yidu.test_57z5 in D:\oss_1\Common
开始 Tue Nov 27 10:12:12 2018
Message: 失败

0 Tue Nov 27 10:12:23 2018
1 Tue Nov 27 10:12:23 2018

Ran 1 test in 21.744s

OK

所以一种很简单的 把元素查找作为条件的 显式等待就出来了,这是可以直接用到自动化脚本中。起码比起强制等待time.sleep()要智能很多的。

下一次分享 显式等待(二)expected_conditions类

交流技术 欢迎+QQ 153132336 zy
个人博客 https://blog.csdn.net/zyooooxie

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

1127UI自动化测试经验分享-显式等待(一)WebDriverWait类、until()方法 的相关文章

随机推荐