Airtest API精讲之断言
上期回顾:Airtest之全局变量
2023.8.26修改,Airtest1.2.7-1.2.8添加了新的断言API
以下基于
python3.8;airtestIDE1.2.11;airtest1.2.2;pocoui1.0.83
断言是每个测试框架都有的,可以理解为测试点检验。Airtest一共有4个断言API,支持所有Android、iOS、Windows平台,分别为:
-
assert_exists:检验图片存在
-
assert_not_exists:检验图片不存在
-
assert_equal:判断预期值与实际值相等
-
assert_not_equal:判断预期值与实际值不相等
源码解析
先来看assert_exists()源码(不想看源码的可以直接跳到后面的演示实例):
# 文件位置:your_python_path/site-packages/airtest/core/api.py
def assert_exists(v, msg=""):
try:
pos = loop_find(v, timeout=ST.FIND_TIMEOUT, threshold=ST.THRESHOLD_STRICT or v.threshold)
return pos
except TargetNotFoundError:
raise AssertionError("%s does not exist in screen, message: %s" % (v, msg))
参数
v:要判断的图片对象
msg:断言描述信息,会显示在报告中
源码很简单,主要就是调用了loop_find(),这个之前在Airtest源码分析--图像识别整体流程讲过这里就不再展开了,只提两点:
1.timeout=ST.FIND_TIMEOUT
,找图超时时间,默认为20s。全局变量之前讲过,详情可以看Airtest之全局变量
2.threshold=ST.THRESHOLD_STRICT or v.threshold
的意思是:如果配置了全局变量ST.THRESHOLD_STRICT,则取其值,否则取图片Template实例中的threshold值(后面会在示例中演示)
整体逻辑就是图片找到返回其坐标;如果图片没找到,loop_find()会报TargetNotFoundError错误,用except接住,换成拋出AssertionError的错误。
我们继续看下assert_not_exists()源码:
def assert_not_exists(v, msg=""):
try:
pos = loop_find(v, timeout=ST.FIND_TIMEOUT_TMP)
raise AssertionError("%s exists unexpectedly at pos: %s, message: %s" % (v, pos, msg))
except TargetNotFoundError:
pass
与assert_exists()正好相反,如果匹配到图片,则拋出AssertionError的错误;如果没匹配到,loop_find()会报TargetNotFoundError错误,用except接住,然后pass使其不报错。
assert_equal()源码:
def assert_equal(first, second, msg=""):
if first != second:
raise AssertionError("%s and %s are not equal, message: %s" % (first, second, msg))
参数
first:预期值
second:实际值
msg:断言描述信息,会显示在报告中
代码就两行,很简单,如果预期值和实际值不一致,拋出AssertionError的错误。
assert_not_equal()源码:
def assert_equal(first, second, msg=""):
if first == second:
raise AssertionError("%s and %s are not equal, message: %s" % (first, second, msg))
如果预期值和实际值一致,拋出AssertionError的错误。
实例演示
# -*- encoding=utf8 -*-
__author__ = "测试工程师小站"
from airtest.core.api import *
# 通过IDE抓取的公众号图标图片
icon70 = Template(r"tpl1637984484238.png", record_pos=(-0.376, -0.787), resolution=(1080, 2340))
# 复制了上面的图片,只是把threshold改为1,实际匹配度不可能达到100%
icon100 = Template(r"tpl1637984484238.png", threshold=1, record_pos=(-0.376, -0.787), resolution=(1080, 2340))
# 断言默认的threshold=0.7的图片存在,通过
assert_exists(icon70, "测试工程师小站图标存在")
# 断言threshold=1的图片存在,不通过
assert_exists(icon100, "测试工程师小站图标相似度1时存在")
# 断言threshold=1的图片不存在,通过
assert_not_exists(icon100, "测试工程师小站图标相似度1时不存在")
执行后,在第2个断言处失败,最后一个断言没执行,我们看下报告:
第1行:第1个断言通过
第2行:第2个断言未通过
第3行:执行失败,显示详细的报错信息
这样存在一个问题,报错后我后面的用例没执行了,我希望断言不通过但能继续执行完,只要加try就行了,如果报错,就只打印一下报错信息。修改后的代码如下:
# -*- encoding=utf8 -*-
__author__ = "测试工程师小站"
from airtest.core.api import *
# 通过IDE抓取的公众号图标图片
icon70 = Template(r"tpl1637984484238.png", record_pos=(-0.376, -0.787), resolution=(1080, 2340))
# 复制了上面的图片,只是把threshold改为1,实际匹配度不可能达到100%
icon100 = Template(r"tpl1637984484238.png", threshold=1, record_pos=(-0.376, -0.787), resolution=(1080, 2340))
# 断言默认的threshold=0.7的图片存在,通过
assert_exists(icon70, "测试工程师小站图标存在")
# 断言threshold=1的图片存在,不通过
try:
assert_exists(icon100, "测试工程师小站图标相似度1时存在")
except Exception as e:
print(str(e))
# 断言threshold=1的图片不存在,通过
assert_not_exists(icon100, "测试工程师小站图标相似度1时不存在")
再次执行,用例可以全部执行完了,看下报告:
第一个断言threshold=0.7存在的通过
第二个断言threshold=1存在的不通过,点击可以在右侧看到详细的报错信息
第三个断言threshold=1不存在的通过
继续看另2个断言示例:
# -*- encoding=utf8 -*-
__author__ = "测试工程师小站"
import re
from airtest.core.api import *
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)
# 公众号名称,取出来文本为:测试工程师小站@,不知道为啥多个@
name = poco("com.tencent.mm:id/a_g").get_text()
# 取@前的文本,即公众号真正的名称:测试工程师小站
name = name[:-1]
# 断言公众号名称是:测试工程师小站。通过
assert_equal(name, "测试工程师小站", "公众号名称正确")
# 取介绍下面的原创内容,即:129篇原创内容 36位朋友关注
num_str = poco("com.tencent.mm:id/a5m").get_text()
# 正则查找第一个数值,即129
searchObj = re.search(r'(\d+)', num_str)
count = searchObj.group(1)
# 断言原创文章不是999,是129嘛,所以通过
assert_not_equal(int(count), 999, "公众号原创文章数不是999")
运行之后看下报告:
第一个断言判断相等,通过
第二个断言判断不相等,通过
那么对于poco框架的执行,有没有像图片一样可以断言元素存在不存在呢?用assert_equal()、assert_not_equal()也是可以实现的。首先poco本身的wait()当判断元素存在时返回的是坐标,我们需要二次封装一下,让其存在返回True,不存在返回False,再用断言和布尔值对比即可。
# -*- encoding=utf8 -*-
__author__ = "测试工程师小站"
from airtest.core.api import *
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)
def my_wait(poco_obj):
"""
传入一个poco对象,判断是否存在,存在返回True,不存在返回False
"""
if poco_obj.wait():
return True
return False
name = poco("com.tencent.mm:id/a_g")
assert_equal(my_wait(name), True, "测试工程师名称元素存在")
这样,执行后,my_wait()返回True,相当于assert_equal(True, True, "测试工程师名称元素存在")
看下报告:
Airtest1.2.7-1.2.8添加了14个新的断言
对其他自动化框架熟悉的朋友,如Pytest,相信对这次新增的14个断言一看便知
-
assert_true
-
assert_false
-
assert_is
-
assert_is_not
-
assert_is_none
-
assert_is_not_none
-
assert_in
-
assert_not_in
-
assert_is_instance
-
assert_not_is_instance
-
assert_greater
-
assert_greater_equal
-
assert_less
-
assert_less_equal
详细的解读,可以看Airtest1.2.7新增的14个断言API解析
---------------------------------------------------------------------------------
关注微信公众号即可在手机上查阅,并可接收更多测试分享~