• 0
  • 0
分享
  • Appium + Python自动化测试学习之:元素等待机制
  • 恬恬圈 2020-03-02 16:58:51 字数 6982 阅读 2446 收藏 0

在我们自动化过程中,能否构建一个健壮和可靠的测试是UI自动化测试能否成功的关键因素之一。然而在自动化过程中试着去执行的时候,常常会出现各种不同的状况,当使用脚本定位元素或者去验证程序的运行状态时,有时候会发现找不到元素,这可能是由于突然的资源受限或者网络延迟或者机器性能等各种因素引起的响应速度太慢导致的,这时候测试报告就会返回测试失败的结果。其实元素是正常加载的,只是加载的时间晚了一点,那么遇到这种情况我们该怎么解决呢?

我们需要在测试脚本中引入延时机制,来使脚本的运行速度与程序元素的加载速度匹配。通俗意义上讲,就是我们需要使脚本和程序的响应能够同步。

我们有三种等待机制,强制等待、隐式等待和显式等待。

如何使用隐式等待或显式等待?

在什么情况下使用隐式等待或显式等待?

什么情况下使用强制等待?


一、隐式等待

隐式等待是通过一定的时长等待页面上某元素加载完成。如果超出了设置的时长元素还没有加载完成,则会抛出NoSuchElementException的异常。

一旦设置,隐式等待时间就会作用于这个webdriver实例的整个周期或者一次完整测试的执行周期,并且webdriver会使其对所有测试步骤中包含整个界面的元素的查找时都有效,除非把默认时间设置回0。

webdriver提供了implicitly_wait()方法来实现隐式等待,默认参数是以秒为单位。如下实例:

from appium import webdriver
from selenium.common.exceptions import NoSuchElementException
import time
desired_caps = {
    'platformName': 'Android',
    'platformVersion': '6.0.1',
    'deviceName':'127.0.0.1:21305',
    'appPackage': 'com.baidu.homework',
    'appActivity': 'com.baidu.homework.activity.index.IndexActivity',
    'automationName': 'Appium',
    'noReset': False,
    # 输入中文参数配置
    "unicodeKeyboard": True,
    "resetKeyboard": True,
}
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)
driver.implicitly_wait(10)
def zuoyebang_login(un="zuoyebang", pw="zuoyebang!test"):
    # 点击未登录按钮
    driver.find_element_by_id("com.baidu.homework:id/rl_login_guide_layout").click()
    # 点击密码登陆
    driver.find_element_by_id("com.baidu.homework:id/sll_password").click()
    #设置隐式等待时间10s
    try:
        # 输入用户名
        print(time.strftime('%H:%M:%S', time.localtime(time.time())))
        driver.find_element_by_id("com.baidu.homework:id/passport_phone_number_input_edit0").send_keys(un)
        # 输入密码
        driver.find_element_by_id("com.baidu.homework:id/passport_password_input_view").send_keys(pw)
    except NoSuchElementException as e:
        print(e)
        print(time.strftime('%H:%M:%S', time.localtime(time.time())))
       
def zuoyebang_login2(un="zuoyebang", pw="zuoyebang!test"):
    try:
        # 输入密码
        print(time.strftime('%H:%M:%S', time.localtime(time.time())))
        driver.find_element_by_id("com.baidu.homework:id/passport_password_input_view1").send_keys(pw)
    except NoSuchElementException as e:
        print(e)
        print(time.strftime('%H:%M:%S', time.localtime(time.time())))
if __name__ == '__main__':
    # 调用登陆方法
    zuoyebang_login()
    zuoyebang_login2()

本例创建了两个登陆方法,并且设置的等待时间是10秒。首先这10秒并不是一个固定的时间,它并不会影响脚本的执行速度;其次,它并不是针对界面上的某一个元素进行等待,它是对整个全局元素进行等待。

当脚本执行到某一个元素定位时,如果元素能够定位到,则继续执行,如果元素定位不到,那么它就将以轮循的方式不断地去判断元素是否被定位到。假设元素在第3秒定位到了则继续执行,若直到10秒(超出设置时长)还没有定位到元素,那么就会抛出异常。

在上面的例子中,故意写错两个resource_id ,所以肯定定位不到元素,通过打印的时间可以看出,当执行输入用户名和密码时,超过了10秒的时间等待,就会理解抛出了异常。并且可以看出它是对全局元素都会进行等待。

Python Shell

14:28:31
Message: An element could not be located
on the page using the given search parameters.
14:28:41
14:28:41
Message: An element could not be located 
on the page using the given search parameters.
14:28:51

隐式等待为webdriver中的完整的一个测试用例或者一组测试的同步,提供了通用的方法。它对于解决由于网络延迟或者动态加载元素所导致的程序响应时间不一致,是非常有效的。


二、显式等待

显式等待是appium中webdriver用于同步测试的另外一种等待机制。显式等待比隐式等待具备更好的操控性。 ,与隐式等待不同,我们可以为脚本设置一些预置或者定制化的条件,等待条件满足后再近些下一步测试。

在使用场景上,隐式等待用来做一个全局的控制,例如设置全局隐式等待6秒;显式等待可以只作用于仅有同步需求的测试用例,它可以只针对某一个元素进行等待。

webdriver提供了WebDriverWait类来实现显式等待,配合该类的until()和until_not()方法,在设置的时间内,默认每隔一段时间去检测一次当前页面下指定的元素是否加载完,加载完了就执行下一步,否则继续每隔一段时间去判断,指定时间截止,如果超时就会抛出异常(TimeoutException)。具体格式如下:

WebDriverWait(driver,timeout=10,poll_frequency=0.5,ignored_exceptions=None)
  • driver:webdriver实例

  • timeout:最长超时时间,默认以秒为单位

  • poll_frequency:检测的时间间隔,默认为0.5秒

  • ignored_exceptions:超时后的异常信息,默认情况下抛出TimeoutException异常

#调用该方法提供的驱动程序作为一个参数,直到返回值为True
until(method,message='')
#调用该方法提供的驱动程序作为一个参数,直到返回Fasle
until_not(method,message="")

如下所示:

WebDriverWait(driver,timeout=10,poll_frequency=0.5,\
              ignored_exceptions=None).until(lambda x :x.find_element_by_id("resource_id"))

实例:

from appium import webdriver
from selenium.common.exceptions import NoSuchElementException, TimeoutException
import time
from selenium.webdriver.support.wait import WebDriverWait
desired_caps = {
    'platformName': 'Android',
    'platformVersion': '6.0.1',
    'deviceName': '127.0.0.1:21305',
    'appPackage': 'com.baidu.homework',
    'appActivity': 'com.baidu.homework.activity.index.IndexActivity',
    'automationName': 'Appium',
    'noReset': False,
    # 输入中文参数配置
    "unicodeKeyboard": True,
    "resetKeyboard": True,
}
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)
def zuoyebang_login(un="zuoyebang", pw="zuoyebang!test"):
    # 点击未登录按钮
    driver.find_element_by_id("com.baidu.homework:id/rl_login_guide_layout").click()
    # 点击密码登陆
    driver.find_element_by_id("com.baidu.homework:id/sll_password").click()
    #设置隐式等待时间10s
    try:
        # 输入用户名
        print(time.strftime('%H:%M:%S', time.localtime(time.time())))
        us=WebDriverWait(driver, timeout=10, poll_frequency=0.5).until(lambda x: x.find_element_by_id("com.baidu.homework:id/passport_phone_number_input_edit0"),message='用户名输入框定位超时')
        us.send_keys("un")
        # 输入密码
        driver.find_element_by_id("com.baidu.homework:id/passport_password_input_view").send_keys(pw)
    except TimeoutException as e:
        print(e)
        print(time.strftime('%H:%M:%S', time.localtime(time.time())))
if __name__ == '__main__':
    # 调用登陆方法
    zuoyebang_login()

上面的实例是每隔0.5秒去判断一次元素是否已经定位到,一直等到10秒,如果超过10秒还没有定位到就会抛出异常。

执行结果如下:

Python Shell

15:48:22
Message: 用户名输入框定位超时
15:48:32

PS:应尽量避免在测试中隐式等待和显式等待混合使用来处理同步问题。相比隐式等待,显式等待能提供更好的可操控性。


三、强制等待

有时候我们希望脚本在执行到某一处位置时做固定时间的休眠,尤其是在脚本调试的过程中。这时候我可以使用time模块提供的sleep()方法。

from appium import webdriver
from selenium.common.exceptions import NoSuchElementException, TimeoutException
import time
from selenium.webdriver.support.wait import WebDriverWait
desired_caps = {
    'platformName': 'Android',
    'platformVersion': '6.0.1',
    'deviceName': '127.0.0.1:21305',
    'appPackage': 'com.baidu.homework',
    'appActivity': 'com.baidu.homework.activity.index.IndexActivity',
    'automationName': 'Appium',
    'noReset': False,
    # 输入中文参数配置
    "unicodeKeyboard": True,
    "resetKeyboard": True,
}
def zuoyebang_login(un="zuoyebang", pw="zuoyebang!test"):
    # 点击未登录按钮
    driver.find_element_by_id("com.baidu.homework:id/rl_login_guide_layout").click()
    # 点击密码登陆
    driver.find_element_by_id("com.baidu.homework:id/sll_password").click()
    #设置隐式等待时间10s
    try:
        # 输入用户名
        print(time.strftime('%H:%M:%S', time.localtime(time.time())))
        time.sleep(10)
        driver.find_element_by_id("com.baidu.homework:id/passport_phone_number_input_editd").send_keys("un")
        # 输入密码
        driver.find_element_by_id("com.baidu.homework:id/passport_password_input_view").send_keys(pw)
    except NoSuchElementException as e:
        print(e)
        print(time.strftime('%H:%M:%S', time.localtime(time.time())))
if __name__ == '__main__':
    # 调用登陆方法
    zuoyebang_login()

在上面的实例中当执行到sleep()方法时会固定休眠10秒,然后再继续执行。sleep()方法默认参数是以秒为单位,如果设置的时长小于1秒,可以用小数表示,如sleep(0.6)表示休眠0.6秒。

Python Shell

16:02:17
Message: An element could not be located on the page using the given search parameters.
16:02:27


版权声明:本文为CSDN博主「px551」的原创文章,遵循CC 4.0 BY-SA版权协议,原文链接:https://blog.csdn.net/px551/article/details/104581449。

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •   随着中国IT业的发展和软件市场的不断成熟,国内人工智能(AI)、物联网、大数据、云计算等IT产业得到了迅速发展。但是,目前中国软件产业在产品功能和性能测试等领域还存在着严重不足。根据Gartner的预测:到2022年,IT行业的开发总成本将从3.76万亿美元增涨至3.87万亿美元。而到了2023年,全球相应的软件测试市场,预计将出现14%的综合年度增涨率。软件市场不断扩大,越来越多的企业认识到软件测试的重要性。在未来,如何应对快速发展的技术变革,是测试行业和测试人员需要面对的挑战。  调查目的  51Testing以测试行业为分析对象,以真实数据为依据,从软件测试从业人员所在公司的基本属性...
            13 13 865
            分享
          •   EA 和 PopCap Studios 的《植物大战僵尸 3》公布了首个游戏预告片,并确定本作将于今年年内面向全球发布。  《植物大战僵尸 3》是一款由宝开游戏(PopCap Studios)开发的手机游戏,支持 iOS 和安卓平台,采用免费 + 内购方式,目前已在英国、荷兰、澳大利亚和菲律宾开启抢先体验。  本作采用分集式叙事方式,在初代游戏玩法的基础上融入了新的故事情节和解谜冒险元素,之前游戏中的许多植物都会回归,并且还会带来一些新植物。  查询发现,《植物大战僵尸》发布于 2009 年 5 月 5 日,后续又在 2013 年推出了其续作,后来又推出了多部衍生作,而本作则是继 2019...
            0 0 817
            分享
          • 1、需求分析前的准备在软件开发过程中,需求分析可以说是核心任务之一,就像一支将要远航的船队,要在指定时间内到达目录地,他们需要一条正确的航线,才能到达目的地,如果航线有误,他们将会误时到达,或是不回到原位将永远到达不了,这么重要的东西,但在国内很多团队中缺少,虽然我也做了一些,但在项目完成的时候,回头看看,其实我们做了很多不必要的事,浪费了很多时间、人力和物力,为保证在今后的开发中减少这些错误的发生,现将一些问题记录下来。为了了解系统需求,先可以从概要式的需求着手,再细化需求,需求分析必须拟定文档,在写文档之前我们必须做好寻求分析的范围,总结为以下几点:1.1 要做一个什么样的系统这个不说,我...
            0 0 1104
            分享
          • 新浪科技讯 9 月 15 日晚间消息,近日,《羊了个羊》小游戏爆火,网上流传一张截图显示,《羊了个羊》小游戏 9 月 14 日收入达到 468 万余元,而本月收入也高达 2565 余万元。随后,腾讯马化腾在相关朋友圈下面评论:核实了是 PS 伪造的。游戏介绍显示,《羊了个羊》是一款超难的闯关消除小游戏,通关率不到 0.1%。《羊了个羊》与多数消除类游戏玩法类似,玩家需将关卡中相同的道具消除。除第一关缺少难度外,游戏第二关难度陡升。不少网友纷纷吐槽“第二关玩了十几遍都没过”“熬夜一晚上没过”等。作者:佚名文章来源:IT之家 (ithome.com)
            0 0 1135
            分享
          • 一、unittest自动化测试结构二、代码实现1、导入需要的一些前置方法,用以获取cookie,生成测试数据等# coding=utf-8 import sys sys.path.append('..') # 导入前置方法(登录接口获取cookie;通用的方法,如生成随机字符串、手机号;一些常用的参数设置等) import PreProcessing as p from PreProcessing import *2、初始化 接口地址、机构、用户、数据库等初始化要查询的数据库,参考htt...
            13 13 2072
            分享
      • 51testing软件测试圈微信