app自动化测试——强制等待、隐式等待、显性等待

在这里插入图片描述


一、强制(直接)等待

为什么要添加等待?
避免页面未渲染完成后操作,导致的报错

原理:强制等待,线程休眠一定时间

二、隐式等待

问题:难以确定元素加载的具体等待时间。
解决方案:针对于寻找元素的这个动作,使用隐式等待添加配置。

原理:隐式等待是一种全局的等待方式,设置一个等待时间,轮询查找(默认 0.5 秒)元素是否出现,如果没出现就抛出异常

隐式等待无法解决的问题

元素可以找到,使用点击等操作,出现报错
原因:
页面元素加载是异步加载过程,通常xml会先加载完成,相应的元素属性后加载
元素存在与否是由xml决定,元素的交互是由属性决定
隐式等待只关注元素能不能找到,不关注元素能否点击或者进行其他的交互

解决方案:使用显式等待

隐式等待设置,一般实例化完driver之后,设置,它是一个全局的等待方式
每一次调用find_element 方法的时候,都会差法隐式等待
每隔0.5s查找一次,如果8秒之内查找到元素,后面的时间就不等待

import time

from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
class TestSleep:
    def setup(self):
        # 创建一个字典,desirecapility
        caps = {
    
    }
        # 系统
        caps["platformName"] = "Android"
        # 设备名称
        caps["deviceName"] = "127.0.0.1:7555 device"
        # 包安卓包名和页面名;获取
        # windows:adb logcat ActivityManager:I | findstr "cmp"
        caps["appPackage"] = "com.xueqiu.android"
        caps["appActivity"] = ".mainnesting.view.MainNestingActivity"
        # todo 保留登录信息
        caps["noReset"] = "true"
        caps["ensureWebviewsHavePages"] = True
        # 创建driver,与appium server建立连接,返回一个session
        # todo driver变成self.driver由局部变量变成实例变量,然后就可以在其他的方法中引用这个变量了
        self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
        #todo 隐式等待设置,一般实例化完driver之后,设置,它是一个全局的等待方式
        # 每一次调用find_element 方法的时候,都会差法隐式等待
        # 每隔0.5s查找一次,如果8秒之内查找到元素,后面的时间就不等待
        self.driver.implicitly_wait(8)
        #缺点:让脚本的执行速度整体变慢


    def teardown(self):
        pass

    def test_sleep1(self):
        time.sleep(8)
        #self.driver.find_element(AppiumBy.ID,"com.xueqiu.android:id/iv_home_tab_config").click()
        element = self.driver.find_element(AppiumBy.ID, "com.xueqiu.android:id/search_input_text").click()
        time.sleep(2)
        element=self.driver.find_element(AppiumBy.ID,"com.xueqiu.android:id/search_input_text")
        element.clear()
        element.send_keys("腾讯")

三、显式等待

WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件)

原理:在最长等待时间内,轮询,是否满足结束

import time

from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions

class TestSleep:
    def setup(self):
        # 创建一个字典,desirecapility
        caps = {
    
    }
        # 系统
        caps["platformName"] = "Android"
        # 设备名称
        caps["deviceName"] = "127.0.0.1:7555 device"
        # 包安卓包名和页面名;获取
        # windows:adb logcat ActivityManager:I | findstr "cmp"
        caps["appPackage"] = "com.xueqiu.android"
        caps["appActivity"] = ".mainnesting.view.MainNestingActivity"
        # todo 保留登录信息
        caps["noReset"] = "true"
        caps["ensureWebviewsHavePages"] = True
        # 创建driver,与appium server建立连接,返回一个session
        # todo driver变成self.driver由局部变量变成实例变量,然后就可以在其他的方法中引用这个变量了
        self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
        # todo 隐式等待设置,一般实例化完driver之后,设置,它是一个全局的等待方式
        # 每一次调用find_element 方法的时候,都会差法隐式等待
        # 每隔0.5s查找一次,如果8秒之内查找到元素,后面的时间就不等待
        self.driver.implicitly_wait(8)
        # 缺点:让脚本的执行速度整体变慢
        # 它只能判断元素存在,(标签出来了,但是,是否可点击,是否可用这些属性没有加载出来,异步加载的)

    def teardown(self):
        pass

    def test_sleep1(self):
        time.sleep(8)
        # self.driver.find_element(AppiumBy.ID,"com.xueqiu.android:id/iv_home_tab_config").click()

        #todo 显性等待 判断元素是否处于可点击的状态
        WebDriverWait(self.driver,10).until(
            expected_conditions.element_to_be_clickable(
                (AppiumBy.ID, "iv_home_tab_config"))
        )

        self.driver.find_element(AppiumBy.ID, "iv_home_tab_config").click()
        time.sleep(2)
        #element = self.driver.find_element(AppiumBy.ID, "com.xueqiu.android:id/search_input_text")
        #element.clear()
        #element.send_keys("腾讯")

显示等待与隐式等待相对,显示等待必须在每个需要等待的元素前面进行声明。
是针对于某个特定的元素设置的等待时间,在设置时间内,默认每隔一段时间检测一次当前页面某个元素是否存在,
如果在规定的时间内找到了元素,则直接执行,即找到元素就执行相关操作,
如果超过设置时间检测不到则抛出异常。默认检测频率为0.5s,默认抛出异常为:NoSuchElementException
显示等待用到的两个类:WebDriverWait和expected_conditions两个类

显式等待可以等待动态加载的ajax元素,显式等待需要使ExpectedCondtions来检查条件
一般页面上元素的呈现

首先出现title
dom树出现presence ,还不完整
css出现 (可见visibility)
js出现,js特效执行(可点击clickable)

html文档是自上而下加载的

app加载方式:
先加载页面框架布局
布局中元素(图片、视频)以异步的方式发送给服务器请求

1、WebDriverWait用法

WebDriverWait用法
WebDriverWait(driver,timeout,poll_frequency=0.5.ignored_exceptions=None)
driver:浏览器驱动
timeout:最长超时时间,默认以秒为单位
poll_frequency:检测的间隔步长,默认为0.5s
ignored_exceptions:超时后的抛出的异常信息,默认抛出NoSuchElementExeception异常。

WebDriverWait 的 until()和until_not()方法:
method:在等待期间,每隔一段时间(__init__中的poll_frequency)调用这个传入的方法,直到返回值不是False
message:如果超时,抛出TimeoutException,将message传入异常
until_not:与until相反,
until是当某元素出现或什么条件成立则继续执行,
until_not是当某元素消失或什么条件
则继续执行,参数也相同。

2、expected_conditions

presence_of_element_located判断元素是否被加载到了DOM树里,并不代表该元素一定可见
用法:
WebDriverWait(driver,timeout,poll_poll_frequency=0.5).until(expected_conditions.persence_of_element_located(元素对象))

3、总结三种等待方式

隐式等待:尽量默认都加上,时间限定在3-6s,不要太长,为了所有的find_element方法都有一个很好的缓冲。
显性等待:用来处理隐式等待无法解决的一些问题,比如:文件上传(可以设置长一点),文件上传需要设置20s以上,但是如果设置隐式等待,它会在每个find方法都等这么长时间,一旦发现没有找到元素,就会等20s以后才抛出异常,影响case的执行效率,这时候就需要用显式等待,显式等待可以设置的长一点。
强制等待:一般不推荐,前两种基本能解决绝大部分问题,一般用于调试。

猜你喜欢

转载自blog.csdn.net/YZL40514131/article/details/129634734