zoukankan      html  css  js  c++  java
  • selenium的三种等待方式

    一、背景

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

    固定等待、隐式等待和显式等待。

    1、time.sleep(固定等待)  

    本质:让当前的线程睡眠,实质是线程的阻塞(blocking),用wait 方式实现。

    缺点:网络条件好浪费时间,严重影响项目的性能

    好处:调试脚本可以用

    2、implicitly_wait(隐式等待)

    本质:在脚本的开始设置一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步;否则可能抛出异常。隐式等待对整个driver周期都起作用,在最开始设置一次就可以了,不要当作固定等待使用。

    缺点:javascript一般都是放在我们的body的最后进行加载,实际这时页面的元素都已经加载完毕,我们却还在等待全部页面加载结束。

    3、WebDriverWait(显式等待)

    本质:动态的等待,判断某一个元素是不是已经出现了,比如title是不是叫百度或百度搜索,根据动态的一些条件来轮询,它会不停的轮询去给我们检测,条件是成功还是失败,比如0.5s就检测一次这个元素在这个条件下是成功还是失败。同时设置轮询的超时时间。

    如果同时设置了显式等待,和隐式等待,就看谁设置的等待时间长,谁的超时等待时间长,就用谁的执行。

    二、WebDriverWait(显式等待)

    1、模块

    from selenium.webdriver.support.wait import WebDriverWait

    2、WebDriverWait 的源码

    # Licensed to the Software Freedom Conservancy (SFC) under one
    # or more contributor license agreements.  See the NOTICE file
    # distributed with this work for additional information
    # regarding copyright ownership.  The SFC licenses this file
    # to you under the Apache License, Version 2.0 (the
    # "License"); you may not use this file except in compliance
    # with the License.  You may obtain a copy of the License at
    #
    #   http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing,
    # software distributed under the License is distributed on an
    # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    # KIND, either express or implied.  See the License for the
    # specific language governing permissions and limitations
    # under the License.
    
    import time
    from selenium.common.exceptions import NoSuchElementException
    from selenium.common.exceptions import TimeoutException
    
    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 
    
                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())
            """
            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)
    
        def __repr__(self):
            return '<{0.__module__}.{0.__name__} (session="{1}")>'.format(
                type(self), self._driver.session_id)
    
        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)

    参数

    webDriverWait参数 含义
    driver 传入WebDriver实例
    timeout 超时时间,等待的最长时间
    poll_frequency 调用util或util_not中的方法的间隔时间,默认是0.5s
    ignored_exceptions 忽略的异常
    方法:util、util_not的参数 说明
    method 在等待期内,每隔一段时间调用这个传入的方法,直到返回值不是False
    message 如果超时抛出TimeoutException,将message传入异常

    三、三种等待方式的实例

    from selenium import webdriver
    from time import sleep
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    # 三种等待方法
    class TestCase(object):
        def __init__(self):
            self.driver = webdriver.Chrome()
            self.driver.get('https://www.baidu.com')
            sleep(2)
    
        def test_sleep(self):
            self.driver.find_element_by_id('kw').send_keys("selenium")
            sleep(2) # 线程的阻塞 blocking wait 方式实现
            self.driver.find_element_by_id('su').click()
            sleep(3)
            self.driver.quit()
    
        def time_implicitly(self):
            self.driver.implicitly_wait(10)
            self.driver.find_element_by_id('kw').send_keys("webdriver")
            self.driver.find_element_by_id('su').click()
            # sleep(2)
            self.driver.quit()
    
        def time_wait(self):
            wait = WebDriverWait(self.driver,2,0.5)
            wait.until(EC.title_is('百度一下,你就知道'))
            self.driver.find_element_by_id('kw').send_keys("webdriver")
            self.driver.find_element_by_id('su').click()
            sleep(2)
            self.driver.quit()
    
    
    if __name__=="__main__":
        case = TestCase()
        # case.test_sleep()
        # case.time_implicitly()
        case.time_wait()

    题外话:

    1、什么是restful:

    https://blog.csdn.net/weixin_41229588/article/details/108219391

    restful资源表现层状态转化

    1)资源:比如一段文字,一张图片,一种服务,一首歌曲等

    2)表现层:资源的表现形式。如文本可以用txt格式,html格式,json格式来表现。

    3)状态转换:http是无状态协议,所有的状态都保存在服务器端,因此如果客户端想要操作服务层,必须通过某种手段,让服务器发生“状态转换”,而这种转化是建立在表现层之上的,所以就是“表现层状态转化”。

    4)客户端用到的手段就是http协议。具体来说就是hppt协议的四种表现方式,如get,post,put,delete。Get 获取资源,post 用来新建资源(更新资源),put用来更新资源,delete 用来删除资源。

    总结一下什么是restful架构:

    每一个uri代表一种资源;客户端和服务器之间传递这种资源的某种表现层;客户端通过http的四种方法,对服务器资源进行操作,实现表现层状态转换。

    2、什么是ajax:

    https://blog.csdn.net/qq_40459545/article/details/111935158

    谈到ajax,首先说ajax不是javaScript的规范,Asynchronous JavaScript and XML的缩写,意思就是用JavaScript执行异步网络请求,Ajax 是一种用于创建快速动态网页的技术,在无需重新加载整个网页的情况下,能够更新部分网页。

    如果仔细观察一个Form的提交,你就会发现,一旦用户点击“Submit”按钮,表单开始提交,浏览器就会刷新页面,然后在新页面里告诉你操作是成功了还是失败了。如果不幸由于网络太慢或者其他原因,就会得到一个404页面。

    这就是Web的运作原理:一次HTTP请求对应一个页面。

    如果要让用户留在当前页面中,同时发出新的HTTP请求,就必须用JavaScript发送这个新请求,接收到数据后,再用JavaScript更新页面,这样一来,用户就感觉自己仍然停留在当前页面,但是数据却可以不断地更新。

    最早大规模使用AJAX的就是Gmail,Gmail的页面在首次加载后,剩下的所有数据都依赖于AJAX来更新。

  • 相关阅读:
    字符串数组
    常用函数
    判断是否是素数回文数
    杨辉三角
    惨痛的教训 没有 脑子的我
    剪缎带
    ?????函数不起作用
    C#3
    celery 原理和组件
    vue检查用户名是否重复
  • 原文地址:https://www.cnblogs.com/hqq2019-10/p/14397900.html
Copyright © 2011-2022 走看看