• airTest 使用体验


    airTest是国内网易自研的一套基于图像识别进行UI自动化测试的框架,目前已经可以支持andriod,ios,web端的UI测试,在google开发者大会上得到了google的高度认可。

    最近在学习使用这个框架,首先来了解下他的原理

    一、 airTest框架的构成

      airTest        ---这里指的是airTest核心源代码

      airTestIDE  ---集成的开发环境,可以快速开发airTest脚本 (注意它自带了python 3.X版本,不能直接使用本地的python库)

      Poco          ---UI 控件检索工具,支持各种客户端

     

    二、 airTest是如何进行识别的?

    众所周知,airTest的最大亮点就是通过图像识别进行UI自动化测试,那么airTest的图像识别是如何进行的呢?

      1. 获取屏幕截图

      2. 根据用户传递的图片与截图进行对比    

       传入的图像需要进行缩放变化,写用例时候的截图进行变换后转换成跑用例时候的截图,以提高匹配成功率

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

      3. 图像匹配,这里用的是openCV的模版匹配和特征匹配

       3.1.模板匹配  cv2.mathTemplate

    def find_template(im_source, im_search, threshold=0.8, rgb=False):
        """函数功能:找到最优结果."""
        # 第一步:校验图像输入
        check_source_larger_than_search(im_source, im_search)
        # 第二步:计算模板匹配的结果矩阵res
        res = _get_template_result_matrix(im_source, im_search)
        # 第三步:依次获取匹配结果
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
        h, w = im_search.shape[:2]
        # 求取可信度:
        confidence = _get_confidence_from_matrix(im_source, im_search, max_loc, max_val, w, h, rgb)
        # 求取识别位置: 目标中心 + 目标区域:
        middle_point, rectangle = _get_target_rectangle(max_loc, w, h)
        best_match = generate_result(middle_point, rectangle, confidence)
        LOGGING.debug("threshold=%s, result=%s" % (threshold, best_match))
        return best_match if confidence >= threshold else None
    
    
    def _get_template_result_matrix(im_source, im_search):
        """求取模板匹配的结果矩阵."""
        # 灰度识别: cv2.matchTemplate( )只能处理灰度图片参数
        s_gray, i_gray = img_mat_rgb_2_gray(im_search), img_mat_rgb_2_gray(im_source)
        return cv2.matchTemplate(i_gray, s_gray, cv2.TM_CCOEFF_NORMED)

         3.2.特征匹配 cv2.FlannBasedMatcher(index_params,search_params).knnMatch(des1,des2,k=2)

    def find_sift(im_source, im_search, threshold=0.8, rgb=True, good_ratio=FILTER_RATIO):
        """基于sift进行图像识别,只筛选出最优区域."""
        # 第一步:检验图像是否正常:
        if not check_image_valid(im_source, im_search):
            return None
     
        # 第二步:获取特征点集并匹配出特征点对: 返回值 good, pypts, kp_sch, kp_src
        kp_sch, kp_src, good = _get_key_points(im_source, im_search, good_ratio)
     
        # 第三步:根据匹配点对(good),提取出来识别区域:
        if len(good) == 0:
            # 匹配点对为0,无法提取识别区域:
            return None
        elif len(good) == 1:
            # 匹配点对为1,可信度赋予设定值,并直接返回:
            return _handle_one_good_points(kp_src, good, threshold) if ONE_POINT_CONFI >= threshold else None
        elif len(good) == 2:
            # 匹配点对为2,根据点对求出目标区域,据此算出可信度:
            origin_result = _handle_two_good_points(im_source, im_search, kp_src, kp_sch, good)
            if isinstance(origin_result, dict):
                return origin_result if ONE_POINT_CONFI >= threshold else None
            else:
                middle_point, pypts, w_h_range = _handle_two_good_points(im_source, im_search, kp_src, kp_sch, good)
        elif len(good) == 3:
            # 匹配点对为3,取出点对,求出目标区域,据此算出可信度:
            origin_result = _handle_three_good_points(im_source, im_search, kp_src, kp_sch, good)
            if isinstance(origin_result, dict):
                return origin_result if ONE_POINT_CONFI >= threshold else None
            else:
                middle_point, pypts, w_h_range = _handle_three_good_points(im_source, im_search, kp_src, kp_sch, good)
        else:
            # 匹配点对 >= 4个,使用单矩阵映射求出目标区域,据此算出可信度:
            middle_point, pypts, w_h_range = _many_good_pts(im_source, im_search, kp_sch, kp_src, good)
     
        # 第四步:根据识别区域,求出结果可信度,并将结果进行返回:
        # 对识别结果进行合理性校验: 小于5个像素的,或者缩放超过5倍的,一律视为不合法直接raise.
        _target_error_check(w_h_range)
        # 将截图和识别结果缩放到大小一致,准备计算可信度
        x_min, x_max, y_min, y_max, w, h = w_h_range
        target_img = im_source[y_min:y_max, x_min:x_max]
        resize_img = cv2.resize(target_img, (w, h))
        confidence = _cal_sift_confidence(im_search, resize_img, rgb=rgb)
     
        best_match = generate_result(middle_point, pypts, confidence)
        print("[aircv][sift] threshold=%s, result=%s" % (threshold, best_match))
        return best_match if confidence >= threshold else None
    
    # 如何找到特征点集
    def _get_key_points(im_source, im_search, good_ratio):
        """根据传入图像,计算图像所有的特征点,并得到匹配特征点对."""
        # 准备工作: 初始化sift算子
        sift = _init_sift()
        # 第一步:获取特征点集,并匹配出特征点对: 返回值 good, pypts, kp_sch, kp_src
        kp_sch, des_sch = sift.detectAndCompute(im_search, None)
        kp_src, des_src = sift.detectAndCompute(im_source, None)
        # When apply knnmatch , make sure that number of features in both test and
        #       query image is greater than or equal to number of nearest neighbors in knn match.
        if len(kp_sch) < 2 or len(kp_src) < 2:
            raise NoSiftMatchPointError("Not enough feature points in input images !")
     
        # 匹配两个图片中的特征点集,k=2表示每个特征点取出2个最匹配的对应点:
        matches = FLANN.knnMatch(des_sch, des_src, k=2)
        good = []
        # good为特征点初选结果,剔除掉前两名匹配太接近的特征点,不是独特优秀的特征点直接筛除(多目标识别情况直接不适用)
        for m, n in matches:
            if m.distance < good_ratio * n.distance:
                good.append(m)
        # good点需要去除重复的部分,(设定源图像不能有重复点)去重时将src图像中的重复点找出即可
        # 去重策略:允许搜索图像对源图像的特征点映射一对多,不允许多对一重复(即不能源图像上一个点对应搜索图像的多个点)
        good_diff, diff_good_point = [], [[]]
        for m in good:
            diff_point = [int(kp_src[m.trainIdx].pt[0]), int(kp_src[m.trainIdx].pt[1])]
            if diff_point not in diff_good_point:
                good_diff.append(m)
                diff_good_point.append(diff_point)
        good = good_diff
     
        return kp_sch, kp_src, good
    
    # sift对象
    def _init_sift():
        """Make sure that there is SIFT module in OpenCV."""
        if cv2.__version__.startswith("3."):
            # OpenCV3.x, sift is in contrib module, you need to compile it seperately.
            try:
                sift = cv2.xfeatures2d.SIFT_create(edgeThreshold=10)
            except:
                print("to use SIFT, you should build contrib with opencv3.0")
                raise NoSIFTModuleError("There is no SIFT module in your OpenCV environment !")
        else:
            # OpenCV2.x, just use it.
            sift = cv2.SIFT(edgeThreshold=10)
     
        return sift   

    以上两个匹配算法,哪个优先匹配上了,就直接返回结果

    三、airTest的简单脚本运行机制

      3.1  打开ariTestIDE,编写一个脚本,默认命名为: untitled.air

      3.2  连接你的设备

      3.3 编写一个简单的脚本

      3.4 运行脚本

    脚本实际显示的信息如下:

    touch(Template(r"tpl1551777086787.png", record_pos=(0.379, 0.922), resolution=(1080, 2160)))
    wait(Template(r"tpl1551778382115.png", record_pos=(-0.003, -0.551), resolution=(1080, 2160)))
    touch(Template(r"tpl1551775745377.png", record_pos=(-0.007, -0.547), resolution=(1080, 2160)))
    text("cmq00002@qq.com")

    其中的record_pos为 【计算坐标对应的中点偏移值相对于分辨率的百分比】;【tpl1551777086787.png】为你在编写脚本时候截图的小图片

    官网: http://airtest.netease.com/

    官方API文档: https://airtest.readthedocs.io/zh_CN/latest/index.html

    参考:https://blog.csdn.net/tianmi1988/article/details/84798720

  • 相关阅读:
    微信小程序wx.uploadFile 上传文件 的两个坑
    小程序 滚动wx.pageScrollTo
    scss定义全局变量引入sass-resources-loader报错
    mac 创建多个全局Path
    《node.js开发指南》partial is not defined的解决方案
    jq 将translate的旋转角度转为数值
    js浮点金额计算精度
    移动端页面弹窗滚动,页面也随之滚动解决方案
    js 禁止右击保存图片,禁止拖拽图片
    小程序md5加密
  • 原文地址:https://www.cnblogs.com/Ronaldo-HD/p/10482147.html
Copyright © 2020-2023  润新知