UI自动化测试框架搭建 —— 借鉴AirTest框架Template定位元素

UI自动化测试框架搭建 —— 借鉴AirTest框架Template定位元素,第1张

在进行UI自动化测试的时候,有些元素难以匹配,需要采用图片比对的方式找到并 *** 作。


阅读一下AirTest的代码来借鉴一下

安装

下载一个AirtestIDE。


下载地址:https://airtest.netease.com/

找到代码入口
  1. 新建一个py脚本

  2. 连接上测试手机

  3. 点击touch并框选一个图片

  4. 使用Pycharm打开该文件

安装airtest
pip install airtest
查看代码 阅读入口代码
# -*- encoding=utf8 -*-
__author__ = "zhongxin"

from airtest.core.api import *
from airtest.cli.parser import cli_setup

if not cli_setup():
    auto_setup(__file__, logdir=True, devices=[
        "android://127.0.0.1:5037/xxxx?cap_method=MINICAP&&ori_method=MINICAPORI&&touch_method=MAXTOUCH", ])

# script content
print("start...")

touch(Template(r"tpl1648886223193.png", record_pos=(-0.343, -0.643), resolution=(1080, 2400)))

# generate html report
# from airtest.report.report import simple_report
# simple_report(__file__, logpath=True)

这个文件旁边还有一个tpl1648886223193.png图片文件

touch()完成了元素的点击 *** 作

阅读touch方法
@logwrap
def touch(v, times=1, **kwargs):
    if isinstance(v, Template):
        pos = loop_find(v, timeout=ST.FIND_TIMEOUT)
    else:
        try_log_screen()
        pos = v
    for _ in range(times):
        G.DEVICE.touch(pos, **kwargs)
        time.sleep(0.05)
    delay_after_operation()
    return pos

传入的对象是Template所以把这段代码简化一下

pos = loop_find(v, timeout=20)
G.DEVICE.touch(pos, **kwargs)

使用了loop_find找到了pos然后touch了一下

根据编写Selenium代码的经验,大概可以猜测G.DEVICE是一个类似driver对象的 *** 作对象

阅读它的代码也可以看出来,不过不看了

阅读loop_find方法
@logwrap
def loop_find(query, timeout=ST.FIND_TIMEOUT, threshold=None, interval=0.5, intervalfunc=None):
    G.LOGGING.info("Try finding: %s", query)
    start_time = time.time()
    while True:
        screen = G.DEVICE.snapshot(filename=None, quality=ST.SNAPSHOT_QUALITY)

        if screen is None:
            G.LOGGING.warning("Screen is None, may be locked")
        else:
            if threshold:
                query.threshold = threshold
            match_pos = query.match_in(screen)
            if match_pos:
                try_log_screen(screen)
                return match_pos

        if intervalfunc is not None:
            intervalfunc()

        # 超时则raise,未超时则进行下次循环:
        if (time.time() - start_time) > timeout:
            try_log_screen(screen)
            raise TargetNotFoundError('Picture %s not found in screen' % query)
        else:
            time.sleep(interval)

简化一下

screen = G.DEVICE.snapshot(filename=None, quality=ST.SNAPSHOT_QUALITY)
match_pos = query.match_in(screen)

这里进行了一次屏幕截图,然后调用了match_in方法

阅读Template.match_in方法

这个方法进入了Template类了,对外除了实例化应该就用了这个类中的这个方法

def match_in(self, screen):
    # screen 当前页面截图
    match_result = self._cv_match(screen)
    G.LOGGING.debug("match result: %s", match_result)
    if not match_result:
        return None
    focus_pos = TargetPos().getXY(match_result, self.target_pos)
    return focus_pos

简化

match_result = self._cv_match(screen)
focus_pos = TargetPos().getXY(match_result, self.target_pos)

阅读 _cv_match方法

@logwrap
def _cv_match(self, screen):
    ori_image = self._imread()
    image = self._resize_image(ori_image, screen, ST.RESIZE_METHOD)
    ret = None
    for method in ST.CVSTRATEGY:
        func = MATCHING_METHODS.get(method, None)
        if func is None:
            raise InvalidMatchingMethodError("Undefined method in CVSTRATEGY: '%s', try 'kaze'/'brisk'/'akaze'/'orb'/'surf'/'sift'/'brief' instead." % method)
        else:
            if method in ["mstpl", "gmstpl"]:
                ret = self._try_match(func, ori_image, screen, threshold=self.threshold, rgb=self.rgb, record_pos=self.record_pos,
                                        resolution=self.resolution, scale_max=self.scale_max, scale_step=self.scale_step)
            else:
                ret = self._try_match(func, image, screen, threshold=self.threshold, rgb=self.rgb)
        if ret:
            break
    return ret

简化一下

上半部分

ori_image = self._imread()
image = self._resize_image(ori_image, screen, ST.RESIZE_METHOD)

ori_image:读取目标图片

在截取tpl1648886223193.png图片文件的时候 IDE把要定位的图片+定位时的屏幕分辨率当做参数传入了Template类中

这时就可以根据(要定位的图片+要定位图片截图时候的屏幕分辨率)+ 当前屏幕的分辨率 + 算法(ST.RESIZE_METHOD) => 缩放后的当前屏幕图片image

下半部分

for method in ST.CVSTRATEGY:
    func = MATCHING_METHODS.get(method, None)
CVSTRATEGY = ["mstpl", "tpl", "surf", "brisk"]
MATCHING_METHODS = {
    "tpl": TemplateMatching,
    "mstpl": MultiScaleTemplateMatchingPre,
    "gmstpl": MultiScaleTemplateMatching,
    "kaze": KAZEMatching,
    "brisk": BRISKMatching,
    "akaze": AKAZEMatching,
    "orb": ORBMatching,
    "sift": SIFTMatching,
    "surf": SURFMatching,
    "brief": BRIEFMatching,
}
ret = self._try_match(func, image, screen, xxx)

遍历4种图片比对算法,得到ret

在math_in方法里面有一句

G.LOGGING.debug("match result: %s", match_result)

也就是这个结果会被打印出来。


查看一下AirtestIDE的日志

[15:57:10][DEBUG] match result: {'result': (170, 508), 'rectangle': ((69, 412.55999999999995), (69, 604.56), (272, 604.56), (272, 412.55999999999995)), 'confidence': 0.9397624135017395, 'time': 0.041297197341918945}

阅读getXY方法

该方法是获得目标的不同位置的坐标

从这里可以看出来result就是匹配到的要点击的图片的中间

rectangle则是要点击图片的四个角的坐标

小结

到此我们可以通过上述代码来实现获取目标位置坐标

接下来把他们拷贝出来整理整理就可以了

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走


这些资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。


希望对大家有所帮助…….在下方我的公众号里免费获取~

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/570436.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存