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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM