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个断言一看便知

  1. assert_true

  2. assert_false

  3. assert_is

  4. assert_is_not

  5. assert_is_none

  6. assert_is_not_none

  7. assert_in

  8. assert_not_in

  9. assert_is_instance

  10. assert_not_is_instance

  11. assert_greater

  12. assert_greater_equal

  13. assert_less

  14. assert_less_equal

详细的解读,可以看Airtest1.2.7新增的14个断言API解析

 

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

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

posted @ 2022-01-01 15:58  ☆星空物语☆  阅读(1145)  评论(0编辑  收藏  举报