appium通過影象識別技術opencv解決無法定位
阿新 • • 發佈:2020-10-25
什麼時候我們需要用到影象識別?
問題1、在我們做 App 自動化測試的時候,會發現很多場景下元素沒有 id、content-desc、text 等等屬性, 並且有可能也會碰到由於開發採用的是自定義 View,View 中的元素也無法識別到,很多的自動化測試框架 對此類場景束手無策。問題2、在做自動化測試的過程中,遇到密碼鍵盤,需要進行模擬點選輸入的問題,使用appium提供的sent_keys方法不管用, 原因是密碼必須得點選密碼鍵盤進行輸入才能夠通過。密碼鍵盤的原理是每次點選一個按鍵,進行一次加密,點選結束後, 按登入才能夠登入通過。而send_keys的輸入方法是直接使用系統的鍵盤傳送鍵值到輸入框,沒有經過點選操作。密碼鍵盤的 一個難點就在於,它沒有id,而appium提供的定位方法大都是通過ID,name,class等元素進行頁面定位的,看過所有的定位方法後, 發現了通過座標值也可以進行定位,而密碼鍵盤要想定位成功,必須通過影象識別,識別出鍵盤所在的位置座標資訊。問題總結:通過傳統的Appium八種元素定位方式無法定位某些特殊場景下的元素,所以要通過影象識別的方式定位座標,最終實現模擬點選。解決App密碼鍵盤無法識別問題的解決思路
這個問題的解決思路如下:1.針對iOS無序鍵盤:首先,iOS的密碼鍵盤是可識別的(和android區別),但是,密碼鍵盤一般是無序的。針對這個情況,思路是用Macaca或者appium-inspector來獲取到每個鍵的資訊的。首先,定義一個數據字典key_num={},把每個鍵的xpath儲存到字典裡面去。這樣key_num裡面儲存的就是key_num[0]="第一個按鍵的xpath路徑",key_num[1]="第二個按鍵的xpath路徑"以此類推,記錄完,整個鍵盤的xpath路徑。然後,通過xpath的值就可以取得該元素的name值,這個值就是該鍵的數字,取name值方式:物件.get_attribute("name")。然後,定義另一個字典keys_num={},來儲存每個按鍵對應的xpath和對應的數字。比如:第一個鍵是“6”,就寫keys_num[6]="第一個鍵的xpath",第二個鍵是“4”,keys_num[4]="第二個鍵的xpath",以此類推,記錄完整個鍵盤的數字和對應的xpath。這樣在輸入密碼的時候,只要遍歷密碼,例如:密碼是“666888”,那麼密碼的第一值是6,我們就取keys_num[6]的值就可以獲取到“數字6”的xpath,在通過get_element_by_xpath("數字6的xpath")方式就可以獲取到該元素,再用 元素.click()進行點選,就可以輸入該值了。2.針對Android無序且無法識別鍵盤#coding:utf-8
import os
import time
import cv2
import numpy as np
import matplotlib.pyplot as plt
def get_pay_keyboard_number_location(im, pwd):
numbers = set(list(pwd))
templates = {}
positions = {}
nimgpath = "" #數字圖片不在同目錄時使用
for i in numbers:
templates[i] = os.path.join(nimgpath, "n{}.jpg".format(i))
start = time.time()
img_rgb = cv2.imread(im)
for teNum, tepath in templates.items():
# print(tepath)
template = cv2.imread(tepath)
h, w = template.shape[:-1]
res = cv2.matchTemplate(img_rgb, template, cv2.TM_CCOEFF_NORMED)
threshold = .95 # 匹配度引數,1為完全匹配
loc = np.where(res >= threshold)
if len(loc) > 0:
positions[teNum] = zip(*loc[::-1])[0]
else:
print("Can not found number: [{}] in image: [{}].".format(tepath, im))
end = time.time()
print(end-start)
return [positions[n] for n in pwd]
if __name__ == "__main__":
ls = get_pay_keyboard_number_location('keyboard.jpg', '1234567890')
print(ls)
上面的程式碼實現了獲取每個數字的座標,並以列表進行返回。拿到座標後就可以直接的通過appium的tap,如TouchAction(driver).long_press(x = 180,y = 1400).perform()
個人總結:注意在擷取圖片時一定要按原圖擷取。思路:利用opencv查詢部分圖片(擷取的),在整體圖片的座標,再利用座標進行點選。關於opencv庫的安裝可參考連結如下:https://blog.csdn.net/ningmengban/article/details/108545451?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param https://www.cnblogs.com/sophia201552/p/12893784.html 文章參考連結:https://blog.csdn.net/ningmengban/article/details/108545451?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param https://blog.csdn.net/jsqfengbao/article/details/77716101?utm_source=blogxgwz4&utm_medium=distribute.pc_relevant.none-task-blog-title-3&spm=1001.2101.3001.4242 https://www.cnblogs.com/baconLiu/p/6727845.html