• 0
  • 0
分享
  • Appium + Python自动化测试学习之:元素等待机制
  • 恬恬圈 2020-03-02 16:58:51 字数 6982 阅读 2102 收藏 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。

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

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •   应届生,没有实际项目经验怎么破?  面试的过程并不为为了显示面试官技术有多牛,也不是为了体现他们公司有多么难进而是考察你的能力和招聘需求是否相匹配,进而评估你能否满足工作需求,甚至实现更多的岗位期待。  弄清楚了这个核心,那么就只需要把控好两方面的内容:  1、自己的技能水平可以满足招聘需求  2、表达能力OK  围绕上面的核心,咱们来具体的聊一下:  首先来说,目前的行业招聘现状是:  ·测试行业底层在不断洗牌  · 初级人员薪资一直维持不变(相当于降薪)  · 已经不再是公司疯狂招人的阶段  所以就导致了明显的两极分化,大厂倾向于直接招测试开发,测试团队进一步精简,...
            0 0 397
            分享
          •   通过执行发现,我们在用例03中没有加入fixture,所有他没有执行一些用例的前置和后置操作。  测试报告  unittest:unittest中没有自带的测试报告,需要下载第三方的插件HTMLTestRunner和BeautifulReport来生成详细的测试报告。  pytest:pytest中也没有自带的测试报告,需要下载第三方插件pytest-html或者allure-pytest进行生成详细的测试报告。class Test01:     def test_01(self):     ...
            11 11 652
            分享
          • 北京时间9月9日早间消息,据报道,索尼指控微软在关于《使命召唤》可以继续支持PlayStation游戏机的问题上对游戏行业和监管者形成误导。在微软宣布斥资750亿美元收购动视暴雪后,这家软件巨头曾经承诺,动视暴雪开发的《使命召唤》系列游戏将会继续支持索尼的PlayStation游戏机。但索尼互动娱乐CEO吉姆·瑞恩(JimRyan)表示,虽然微软“承诺”将同时在PlayStation和微软自家的Xbox游戏机上发布未来版本的《使命召唤》游戏,但实际上,微软只会让这款游戏在PlayStation上保留有限的几年。英国竞争和市场管理局(CMA)上周威胁称,他们将对微软展开深入调查。而其他地区的监管...
            0 0 841
            分享
          • 在做并发测试时,遇到了设置持续时间,但是到达了持续时间后,一直不停止;线程组设置的信息如下:从图中线程组设置可以看出Jmeter需要开启100个线程并且在300s内持续性的给后端服务器发请求,运行后从右上角看到,已经运行超过了300s,但是线程一直没有停止。从jemeter.log 日志查看不停的打印Stopping because end time detected by thread从网上查资料得知是因为某些线程被阻塞了,出现线程阻塞的原因是JMeter的所申请的内存不足导致的,解决该问题有几种方法:调整脚本,可以通过调整并发数、减少断言,尽量不要使用监听器来减少额外的内存开销非GPU模式...
            0 0 15133
            分享
          •   测试工程师经常遇到的问题有:  · 开发的提测质量不佳,开始提测之后明明还有许多功能没有开发完整就提测,导致测试延期  · 经常出现功能漏测的情况,无法保障产品质量  · 经常出现明明测试过的功能,测试通过之后又出现重复的bug  · 测试环境没问题,但是线上环境就是出现了问题  针对第一种提测质量不佳的情况  测试同学做到规范冒烟测试流程,可以提高开发的产品质量意识,冒烟测试通过之后才算正式进入提测环节,这样可以很好的判断到底是因为开发质量问题延期,还是测试慢延期。  冒烟自测流程如下:  QA同学负责用例输出,开发同学执行接口/功能/场景用例,QA同学负责复杂场景及功能走查验收。  项...
            17 17 1360
            分享
      • 51testing软件测试圈微信