您好,登錄后才能下訂單哦!
Appium在Android UI測試中的應用實踐是怎樣的,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
Android 測試工具與 Appium 簡介
Appium 是一個 C/S 架構的,支持 Android/iOS Native, Hybrid 和 Mobile Web Apps 的測試框架,與測試程序通過 Selenum Webdriver 協議通訊。Webdriver 的好處是通過 HTTP RPC 的方式調用 Server 上的過程,編寫測試腳本不受語言的限制,無論是 Python, Java, NodeJS 均可以方便的編寫測試。本文中將使用 Python 進行編程。
起因是因為市場部的同事拋來如下需求:批量添加一些微信好友。直接抓取請求進行重放的方法是不靠譜的,微信與服務端的通訊均加密,Pass。考慮使用 xposed 等框架 hook 相關函數進行操作。但是 xposed 需要越獄,且開發復雜,Pass。后來想到了使用 UI 測試工具進行模擬操作,開發較為簡單。
Android UI 測試工具有很多種,如 Monkey, UIAutomator, Selendroid, Robotium 等。其中 UIAutomator, Monkey, Selendroid 均為非侵入式的 UI 測試,也就是不需要修改源代碼,只要安裝了目標程序就可以進行測試。Robotium 需要與源碼一同編譯測試。Appium 實際上就是一個測試工具的統一調度軟件,將不同的非侵入式測試工具整合在一起,對外提供統一的 API。在 Android 2.3 以前的版本,Appium 會調用 Selendroid ,之后的版本會直接使用 UIAutomator,iOS 下使用 UIAutomation。Appium 還支持 FirefoxOS 的 UI 測試。
安裝 Appium
官網給出了命令行下的安裝方法。但實際上 Appium 有 GUI 版本,更適合在 Windows/MacOS 下使用。Windows 下需要安裝 .NET Framework。
> brew install node # get node.js > npm install -g appium # get appium > npm install wd # get appium client > appium & # start appium > node your-appium-test.js
Appium 需要依賴 Android SDK 編譯在手機端運行的兩個插件,因此需要首先安裝相應的 Android SDK 版本。這里直接使用了 Android Studio 中自帶的 SDK Manager。在 SDK Manager 中選擇和測試機相對應的 SDK Platform 和較新的 Build-tools,如果需要使用模擬器測試還要裝對應的 ARM/x86 System Image,以及 Intel HAXM Installer,用于加速 x86 虛擬機。Appium 使用 adb 來與目標機器通訊,因此對于真機和模擬器操作幾乎都是相同的,如何建立模擬器在此不再贅述。
安裝完成后需要在 Appium GUI 中配置 Android SDK 目錄,隨后選擇 Android,點擊 Launch 就可以啟動 Appium Server。
Appium Server 默認會監聽 http://localhost:4723 ,用于 RPC 通訊。下面我們就可以打開熟悉的編程環境,編寫 UI 測試用例了。這里使用 Python 進行編寫,需要先安裝 Appium 的 Python Client ,然后再 python 中使用 appium.webclient 就可以連接 Appium server了。
pip install Appium-Python-Client
使用 Appium 進行 UI 控制
根據注釋修改相應屬性后即可運行測試。手機需要打開 ADB 調試,執行完以下代碼后,Appium 會在手機上安裝 Appium Settings 和 Unlock 兩個程序,隨后微信會被啟動。
from appium import webdriver desired_caps = {} desired_caps['platformName'] = 'Android' #測試平臺 desired_caps['platformVersion'] = '5.1' #平臺版本 desired_caps['deviceName'] = 'm3_note' #設備名稱,多設備時需區分 desired_caps['appPackage'] = 'com.tencent.mm' #app package名 desired_caps['appActivity'] = '.ui.LauncherUI' #app默認Activity dr = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) #啟動Remote RPC
Selenum Webdriver 使用了一種類似于 JS 中的 DOM 模型的方法來選擇頁面中的元素。dr 為當前正在活動的 activity 對象,可以使用 findElementByXXX 的方法來獲取 Activity 中的元素。所有 Element 后帶 s 的函數,均獲得所有匹配的元素,不帶 s 的函數獲得***個匹配的元素。
查詢函數
1. findElement(s)ByName
在 Android 中基本沒用。Android UI 沒有 Name 這個屬性。有說可以使用 text 值獲取。但我并沒有成功
2. findElement(s)ByClassName
通過類名來獲取元素,用法如下:
item_list = dr.find_elements_by_class_name("android.widget.LinearLayout") item_list[2].click()
3. findElementById
通過 resource_id 來獲取元素,每個 Activity 中都是***的,用法如下
t = dr.find_element_by_id("com.tencent.mm:id/f7") t.send_keys(wechatId)
4. findElement(s)ByAccessbiltiyId
在 Android 上 AccessbilityID 實際就是 contentDescription 。這個屬性是為了方便視力受損人士使用手機所設置。開啟 TTS 后系統會朗讀相關控件的 contentDescription。
5. findElement(s)ByXPath
通過 XML Path 描述來尋找元素。我沒有成功的獲取到,可能是 XPath 寫的有問題。
s = dr.find_element_by_xpath("//android.widget.TextView[contains(@text,'搜索')]") s.click()
6. findElementByAndroidUIAutomator
通過 UIAutomator 的選擇器來獲取元素。因為 Appium 在 Android 上實際是調用的 UIAutomator,所以可以通過 UIAutomator 的選擇器來選擇元素。
el = dr.find_element_by_android_ui_automator("new UiSelector().text(\"搜索\")") el.click()
操作函數
操作函數用于操作選定的元素,有很多,以下僅列舉幾個,更多的請查閱手冊。
click
send_keys
clear
查詢函數返回的元素對象可以像 JS 中的 dom 元素一樣,繼續使用查詢函數來選定其子元素。用例如下。
search = dr.find_element_by_id("com.tencent.mm:id/aqw").find_element_by_class_name("android.widget.RelativeLayout") search.click()
如何確定查詢規則
了解了相關的函數后,下面就應對 UI 進行定位了。如果是自己團隊開發的程序,推薦讓開發同學在所有的空間上都添加 resource_id 進行絕對定位。如果碰到沒有談價 resource_id 的元素,那就要使用別的辦法進行定位了。
1. UI Automator Viewer
UI Automator Viewer 是 Android 官方的 UI 定位工具,位于 sdk/tools 下。運行后會打開 viewer 界面。點擊獲取按鈕即可獲取當前正在運行的 Activity 的 UI 結構。
2. AppiumDriver getPageSource
AppiumDriver(Client) 可以很方便的獲得當前正在運行的 Activity 的 UI 描述,隨后可根據返回的 XML 文檔來尋找元素。
print dr.page_source
確定元素位置后,即可根據前述的 Find 方法來查找/選擇元素
編寫完整的測試代碼
正確的獲取元素之后便可以獲取元素相關的信息,隨后使用各語言常用的測試框架編寫測試即可,如 Java 的 JUnit,Nodejs 的 Mocha 等。
這里我使用 Appium 主要是為了模擬用戶點擊添加微信好友,所以完整的程序并沒有使用到測試框架。相關的 UI 元素獲取/操作方法供大家參考。
# coding:utf-8 from appium import webdriver from time import sleep def addFriend(dr, id, dryRun=False): succ = False wechatId = str(id) dr.find_element_by_accessibility_id(r"更多功能按鈕").click() item_list = dr.find_elements_by_class_name("android.widget.LinearLayout") try: item_list[2].click() except: print "Error! in item list len" return succ el = dr.find_element_by_class_name("android.widget.ListView") item_list = el.find_elements_by_class_name("android.widget.LinearLayout") try: item_list[1].click() except: print "Error! in item list len" return succ t = dr.find_element_by_id("com.tencent.mm:id/f7") t.send_keys(wechatId) search = dr.find_element_by_id("com.tencent.mm:id/aqw").find_element_by_class_name("android.widget.RelativeLayout") search.click() try: freq = dr.find_element_by_id('com.tencent.mm:id/aqq') assert freq.text == u"操作過于頻繁,請稍后再試。" print "Frequency too high! Sleep 300s" sleep(60) return succ except: pass try: dr.find_element_by_id('com.tencent.mm:id/a8x').click() addBtn = dr.find_element_by_id('com.tencent.mm:id/eu') if not dryRun: addBtn.click() succ = True print "Success Send Requests:" + wechatId except: print "No Such User Or Already a Friend:" + wechatId while True: try: dr.find_element_by_id('com.tencent.mm:id/fb').click() except: try: dr.find_element_by_id('com.tencent.mm:id/f4').click() except: break return True def resetActivity(dr, desired_caps): dr.start_activity(desired_caps['appPackage'], desired_caps['appActivity']) desired_caps = {} desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '5.1' desired_caps['deviceName'] = 'm3_note' desired_caps['appPackage'] = 'com.tencent.mm' desired_caps['appActivity'] = '.ui.LauncherUI' print "Trying connect to phone..." dr = {} try: dr = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) except Exception, e: print "Cannot Connect to phone :", e exit() print "Successfully connect to phone." print "Reading friend list..." friendList = [] fp = open("friends.txt") line = fp.readline().strip() while line: friendList.append(line) line = fp.readline().strip() print "Finish reading friends. Total: " + str(len(friendList)) print "Wait for Wechat's splash screen...." for i in range(0, 10): print 10 - i sleep(1) succ_list = [] fail_list = [] for i in friendList: try: succ = addFriend(dr, i, dryRun=False) if succ: succ_list.append(i) else: fail_list.append(i) except: fail_list.append(i) resetActivity(dr, desired_caps) print "Succeed List:" print "\n".join(succ_list) print "Failed List:" print "\n".join(fail_list) dr.close()
看完上述內容,你們掌握Appium在Android UI測試中的應用實踐是怎樣的的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。