异常处理¶
在写测试用例时,以下4种异常是需要处理的,其他的异常多数是脚本的bug,如果你觉得是poco的问题,不要犹豫,随时给我们提issue。
InvalidOperationException
¶
这个异常特指无效的操作,或者说不起作用的操作,例如点击到了屏幕外面,或者对一个图片设置text属性(输入框才能设置text属性)。虽然这个异常并不会对应用造成什么实质性影响,但是还是要尽可能避免,以免测试脚本里逻辑混乱或测试结果不稳定。
# coding=utf-8
from poco.drivers.unity3d import UnityPoco
from poco.exceptions import InvalidOperationException
poco = UnityPoco()
try:
poco.click([1.1, 1.1]) # click outside screen
except InvalidOperationException:
print('oops')
PocoNoSuchNodeException
¶
如果从一个不存在的UI控件读取属性或控制它,那就会出现这个异常。测试一个UI控件是否存在可以调用UI代理的 .exists()
方法。
注解
- 如果只是选择了一个UI但是不去操作或者读取属性是不会产生异常的,因为选择UI只是将选择的条件存储下来,等到执行具体的操作时才会去game/app中查找和选择。
- 如果有个透明的UI或者你看不见(在屏幕外面或者尺寸为0),他同样也是存在的,同样也可以对他进行操作或者读取属性。只有不在hierarchy树中的才是不存在的。

# coding=utf-8
from poco.drivers.unity3d import UnityPoco
from poco.exceptions import PocoNoSuchNodeException
poco = UnityPoco()
node = poco('not existed node') # select will never raise any exceptions
try:
node.click()
except PocoNoSuchNodeException:
print('oops!')
try:
node.attr('text')
except PocoNoSuchNodeException:
print('oops!')
print(node.exists()) # => False. this method will not raise
PocoTargetTimeout
¶
这个异常只会在你主动等待UI出现或消失时抛出,和 PocoNoSuchNodeException
不一样,当你的操作速度太快,界面来不及跟着变化的话,你只会遇到 PocoNoSuchNodeException
而不是 PocoTargetTimeout
,其实就是在那个UI还没有出现的时候就想要进行操作。
下面的例子展示测试脚本如何与UI保持同步,并处理 PocoTargetTimeout
异常

# coding=utf-8
from poco.drivers.unity3d import UnityPoco
from airtest.core.api import connect_device
from poco.exceptions import PocoTargetTimeout
poco = UnityPoco()
# UI is very slow
poco('btn_start').click()
star = poco('star')
try:
star.wait_for_appearance(timeout=3) # wait until appearance within 3s
except PocoTargetTimeout:
print('oops!')
time.sleep(1)
PocoTargetRemovedException
¶
与上面 PocoTargetTimeout
不同,如果操作速度远远慢于UI变化的速度,那*很可能*会出现这个异常。这个异常仅当去访问或操作一个刚才还在但现在不在的UI控件才会出现,并且一般情况下基本不会出现。
下面例子展示点击一个已经不存在的UI控件的效果
# coding=utf-8
from poco.exceptions import PocoTargetRemovedException, PocoNoSuchNodeException
poco = Poco(...)
start = poco('start')
print(start.exists()) # => True.
start.click()
print(start.exists()) # => False
try:
start.click()
except PocoTargetRemovedException:
print('oops!')
# IMPORTANT NOTE:
# `start2` is different from `start` !
# `start` is tracking the UI at initial and it knows itself was removed but `start2`
# does not know anything before.
start2 = poco('start')
try:
start2.click()
except PocoNoSuchNodeException:
print('oops!')
注解
这个异常仅会在一些poco-sdk实现中,所以更可靠的做法是必要的情况下显示地去调用 .exists()
去判断UI是否存在。
注解
In poco.drivers.std.StdPoco
, this exceptions is never raised!
# coding=utf-8
from poco.drivers.unity3d import UnityPoco
from airtest.core.api import connect_device
poco = UnityPoco()
# no PocoTargetRemovedException case
start = poco('start')
print(start.exists()) # => True.
start.click()
print(start.exists()) # => False
# IMPORTANT: In Unity3d, this operation will click the same coordinate as previous
# and no matter what actually happens
start.click()
更多示例: