Poco API精讲之 等待 wait

上期回顾:Poco API精讲之元素属性操作attr、setattr……


以下基于
python3.8;airtestIDE1.2.13;airtest1.2.4;pocoui1.0.85

注意:Poco框架和Airtest框架很多API是同名的,但使用方法完全不一样!!!一定不要搞混了,我初学时也经常搞混,这点一定要注意!
具体Poco框架和Airtest框架是什么关系,可以看之前文章:Airtest Project——UI自动化利器介绍

之前讲了Poco元素定位与属性,今天我们讲下自动化测试中重要的一种操作——等待,自动化脚本健壮性好不好,关键看你等待用的好不好。Poco框架中一共有5种等待方法,分别是wait、wait_for_appearance、wait_for_disappearance、wait_for_any、wait_for_all,下面依次详细看下各个方法怎么用。

1.wait(timeout=3)

等待元素X秒。

参数:
timeout - 等待时间,默认3秒

返回:
自身

源码解析:

# 源码位置:your_python_path\site-packages\poco\proxy.py
    def wait(self, timeout=3):
        start = time.time()
        while not self.exists():
            self.poco.sleep_for_polling_interval()
            if time.time() - start > timeout:
                break
        return self

源码的核心逻辑就是通过while循环,使用Poco框架的exists()方法判断元素是否出现了。
如果出现了则不符合while循环条件退出循环;
如果没出现,等待1.44秒(sleep_for_polling_interval就是等待固定1.44秒)后判断是否达到超时时间,时间达到使用break强制退出循环。
最后不管等没等到,都返回元素对象本身。

我们再来看下exists()的源码,是怎么判断元素是否出现的。

# 源码位置:your_python_path\site-packages\poco\proxy.py
        try:
            return self.attr('visible')
        except (PocoTargetRemovedException, PocoNoSuchNodeException):
            return False

很简单,返回元素的'visible'属性,如果元素出现了,其'visible'属性将是True,即返回True。如果元素没出现,因为属性不存在会报错,所以放在try…except中,并返回False。

一定要注意Poco框架的wait()、exists()和Airtest框架的wait()、exists()是不一样的。可以对比着看看:Airtest API精讲之wait(),exists()

所以Poco框架的wait(),如果等到元素则提前返回;如果在设定时间内没等到也会返回,不会报错。另外wait()之所以返回元素对象本身,是为了代码可以接着写方便。

示例:

from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco

auto_setup(__file__)

poco = UnityPoco()

# 等待元素60秒,如果其出现则立马点击。
# 如果一直没出现,则元素不存在,click会导致PocoNoSuchNodeException报错
poco('测试工程师小站').wait(60).click()


# 等待元素3秒,如果其出现才点击,避免了元素不存在,直接点击导致的报错
qa_button = poco('测试工程师小站')
if qa_button.wait():
    qa_button.click()

2.wait_for_appearance(timeout=120)

等待元素出现,等到提前结束,等不到报错

参数:
timeout - 等待时间,默认120秒

返回:
None

异常:
PocoTargetTimeout:等待元素超时

源码解析:

# 源码位置:your_python_path\site-packages\poco\proxy.py
    def wait_for_appearance(self, timeout=120):
        start = time.time()
        while not self.exists():
            self.poco.sleep_for_polling_interval()
            if time.time() - start > timeout:
                raise PocoTargetTimeout('appearance', self)

通过源码可以看出,wait_for_appearance()和wait()很像,就最后两行代码不一样。区别就是wait_for_appearance()没有返回,且如果没等到元素,会报错。具体使用上的区别看示例。

假设场景:
我们想点击登陆按钮,之后用例才能继续进行,如果登陆不了,用例也就不用执行下去了。在点击登陆按钮之前,有50%几率会弹一个提醒,如果弹了提醒必须点掉,否则就点击不到登陆了。

示例:

from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco

auto_setup(__file__)

poco = UnityPoco()

tips = poco('提醒')
login = poco('测试工程师小站登陆')

# 这里提醒只是几率出现,所以即使不出现,也是正常的,无需报错
if tips.wait(10):  # 等待提醒框最多10秒
    tips.click()  #  如果提醒框出现则点掉,否则影响点击登陆

# login的poco对象定义可以提前定义,定义不会执行
# 只有对象在进行操作时,才会去真正查找,所以Poco适合PO模型
# 这里如果找不到登陆按钮,后面的用例流程也执行不了,所以要报错退出
login.wait_for_appearance()  # 死等登陆120秒,不出现我就报错
login.click()  # login如果出现了,就可以执行该行的点击了

3.wait_for_disappearance(timeout=120)

等待元素消失,消失则提前结束,timeout秒仍未消失则报错

参数:
timeout - 等待时间,默认120秒

返回:
None

异常:
PocoTargetTimeout:等待元素超时

源码解析:

# 源码位置:your_python_path\site-packages\poco\proxy.py
    def wait_for_disappearance(self, timeout=120):
        start = time.time()
        while self.exists():
            self.poco.sleep_for_polling_interval()
            if time.time() - start > timeout:
                raise PocoTargetTimeout('disappearance', self)

wait_for_disappearance的源码就比wait_for_appearance源码少了一个not,就不再多讲了

4.wait_for_any(objects, timeout=120)

等待给定元素列表中任一元素出现,并返回该元素

参数:
objects - 元素列表
timeout - 等待时间

返回:
出现的UIObjectProxy实例

异常:
PocoTargetTimeout:等待元素超时

源码解析:

# 源码位置:your_python_path\site-packages\poco\pocofw.py
    def wait_for_any(self, objects, timeout=120):
        start = time.time()
        while True:
            for obj in objects:
                if obj.exists():
                    return obj
            if time.time() - start > timeout:
                raise PocoTargetTimeout('any to appear', objects)
            self.sleep_for_polling_interval()

等待的源码都是差不多的,wait_for_any就是用了一个for循环去遍历看元素列表中的元素是否有一个出现,只要有1个出现,就立马返回该元素。如果超时了一个没出现,就报错了。

示例:

from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco

auto_setup(__file__)

poco = UnityPoco()

# 屏幕上会随机出现1元、10元、100元,点了就是你的!
# 那妥了,不管出现多少钱,我都点啊,不要白不要,要了还想要!
m1 = poco('monkey1')
m10 = poco('monkey10')
m100 = poco('monkey100')
# 如果1元出现,monkey对象就是1元,如果10元出现,monkey对象就是10元...
monkey = wait_for_any([m1,m10,m100])
monkey.click()

5.wait_for_all(objects, timeout=120)

等待所有元素出现

参数:
objects - 元素列表
timeout - 等待时间

返回:
None

异常:
PocoTargetTimeout:等待元素超时

源码解析:

# 源码位置:your_python_path\site-packages\poco\pocofw.py
    def wait_for_all(self, objects, timeout=120):
        start = time.time()
        while True:
            all_exist = True
            for obj in objects:
                if not obj.exists():
                    all_exist = False
                    break
            if all_exist:
                return
            if time.time() - start > timeout:
                raise PocoTargetTimeout('all to appear', objects)
            self.sleep_for_polling_interval()

核心就是通过for循环去判断元素列表中元素是否都出现了,如果都出现了则返回;如果有一个没出现,就接着找,直到超时报错。
其中while内的前5行代码有一个隐藏的逻辑,就是每次遍历查找所有元素,必须都在了才行。如果第1轮查找,元素1在,元素2没在,第2轮时元素1要重新确认在,防止元素1又消失了。

示例:

from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco

auto_setup(__file__)

poco = UnityPoco()

# 这次规则变了,屏幕上会随机出现1元、10元、100元,但只有1次点击收取按钮的机会
# 为了利益最大化,所以要等所有钱全出现了,再点击收取按钮
m1 = poco('monkey1')
m10 = poco('monkey10')
m100 = poco('monkey100')
get = poco('收取')

wait_for_all([m1,m10,m100])  # 等1元、10元、100元全出现
get.click()

好了,以上就是Poco的5种等待,你学废了吗:)

 

---------------------------------------------------------------------------------

关注微信公众号即可在手机上查阅,并可接收更多测试分享~

posted @ 2022-04-30 17:44  ☆星空物语☆  阅读(2466)  评论(0编辑  收藏  举报