appium介紹
Appium是一個免費分發的開源移動應用UI測試框架。
Appium的設計理念
Appium是使用Node.js平台編寫的“HTTP Server”,並使用Webdriver JSON線協議驅動iOS和Android會話。 因此,在初始化Appium Server之前,必須在系統上預先安裝Node.js 當Appium被下載並安裝時,在我們的機器上設置一個暴露REST API的服務器Appium支持任何支持HTTP請求的語言,如Java,JavaScript與Node.js,Python,Ruby,PHP,Perl等。
編寫Appium測試的基本要求
驅動程序客戶端:Appium驅動移動應用程序,就像它是用戶一樣。 使用客戶端庫編寫您的Appium測試,其中包含您的測試步驟,並通過HTTP發送到Appium服務器。
應用會話:您必須首先初始化一個會話,因為這樣的測試會在會話中進行。 一旦自動化完成一個會話,它可以結束並等待另一個會話
所需功能:要初始化Appium會話,您需要定義名為“所需功能”的某些參數,如PlatformName,PlatformVersion,設備名稱等。 它指定了從Appium服務器需要的自動化類型。
驅動程序命令:您可以使用大型和表達式的命令詞匯編寫測試步驟。
使用Appium可能遇到的錯誤
錯誤1:需要以下所需的功能,但不提供:設備名稱,platformName
錯誤2:找不到adb。請使用Android SDK根目錄路徑設置ANDROID_HOME環境變量
錯誤3:openqa.selenium.SessionNotCreatedException:無法創建新的會話
錯誤4:如何在移動應用程序中查找DOM元素或XPath?
區分Appium和Selenium
Selenium: Selenium 是一個開源(免費)自動化測試框架,用於跨多個瀏覽器和平台驗證 Web 應用程序。Selenium 測試腳本可以用多種編程語言編寫,包括 Java、C#、Python 等。
以下是 Appium 和 Selenium 之間的區別:-
基於使用:
- Appium - Appium 是一種流行的自動化測試開源軟件,尤其是在原生應用程序(如 Android 和 iOS 應用程序)中。它還可以用於在 Android 和 iOS 環境中運行的混合應用程序中。這種類型的自動化測試可確保一旦應用程序投入生產,任何特定補丁安裝都不會出現系統性問題。它確保了完整的集成測試,並避免了測試人員的大量體力勞動。通過使用 Appium,用戶可以輕松避免每次手動測試整個應用程序的每個功能。
- Selenium - Selenium 是一種通用的自動化測試工具,專為任何類型的 Web 應用程序構建。它兼容當前所有流行的瀏覽器和操作系統,如 Windows、Linux 和 MACOS。
基於設計:
- Appium - Appium 主要用作 HTTP 服務器,因為它將處理任何類型的移動應用程序。但是,它主要是在 node JS 中遵循或開發相同的,而不是使用標准的 Java 或 JS 代碼。因此,想要在任何類型的移動應用程序中使用 Appium 進行自動化測試的開發人員必須先在他們的系統上安裝 Node JS,然后才能使用 Appium 工具。
- Selenium - Selenium 主要用於維護 Web 應用程序或網頁上的自動化邏輯。它的創建方式使其可以通過使用瀏覽器活動快速輕松地與應用程序交互。
1.准備工作
java-jdk安裝(appium啟動必須要求安裝Java)
appium安裝
adb安裝
appium 模塊Appium-Python-Client安裝
2.各個應用安裝說明
java-jdk
這個安裝,需要注意環境變量的配置
配置jdk,新建環境變量(系統變量) JAVA_HOME,如圖所示:
系統變量->找到 Path 變量->編輯->在變量值的末尾添加;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin
如果在你下載的文件里面找不到jre/bin的文件,即下面這個目錄,一定要以管理員模式打開cmd,進入java的jdk安裝目錄,輸入
bin\jlink.exe --module-path jmods --add-modules java.desktop --output jre 回車即可。
檢驗方式
輸入java -version,查看版本。
參考鏈接:https://zhuanlan.zhihu.com/p/360519888
Appium
是一個開源工具,用於自動化 iOS 手機、 Android 手機和 Windows 桌面平台上的原生、移動 Web 和混合應用。連接手機,啟動安裝后界面如下
下載鏈接:https://appium.io/
adb安裝
這個目的是為了下發手機相關命令,下載后注意手動去配置環境變量。
下載鏈接:https://developer.android.google.cn/studio?hl=zh-cn
Appium-Python-Client
這個強烈建議不要下載最新版本,后續自動化測試,會導致和appium某些功能不適配,建議下載Appium-Python-Client版本在1.3.0或1.3.0以下。
(過程中可能會出現Method has not yet been implemented的報錯,此錯誤是因為appium sever的版本和Appium-Python-Client 的版本不一致)
下載鏈接:http://appium.io/downloads.html
3.appium連接手機配置
我的p40pro手機,配置如下:
啟動后效果:
python啟動,基本參數配置如下
from appium import webdriver from selenium.webdriver.common.by import By desired_caps = { "platformName": "Android", # 操作系統 "deviceName": "UQG5T20610006585", # 設備 ID adb devices "platformVersion": "10", # 設備版本號 "appPackage": "com.tencent.mm", # app 包名 "appActivity": "com.tencent.mm.ui.LauncherUI", # app 啟動時主 Activity 'noReset': True, # 是否保留 session 信息,可以避免重新登錄 'autoLaunch Appium': True, 'automationName': 'UiAutomator1', 'unicodeKeyboard': True, # 使用 unicodeKeyboard 的編碼方式來發送字符串 'resetKeyboard': False # 將鍵盤給隱藏起來 } driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) print("微信啟動")
這里需要注意其中的automationName這兩個參數,如果這個參數報錯,那么可能是UiAutomator2,以報錯說明為准
以下是參考網上,微信對刪除自己的人的清除操作的代碼,有一下幾個注意點:
1. find_element_by_id方法的廢棄,現在統一為了find_element
2.手機上滑,坐標系的取值,即driver.swipe(x1, y1, x1, y2, duration=500)方法,y2與y1之間盡量差距小一點,滑動點小一點,這樣獲取微信好友不容易漏掉
3.代碼中所有的定位元素id參數修改,如driver.find_elements(By.ID, 'com.tencent.mm:id/hga')中的com.tencent.mm:id/hga。
微信版本變化,它的id值可能都會變化。我拿過來這段代碼,當中所有的定位元素基本都做了修改
4.微信好友名稱的特殊化處理,有的微信名稱里面,有花花草草貓貓狗狗,特殊表情符號這些。雖然都能獲取到,但是逐個取值,搜索欄搜索定位過程可能導致搜索不到最終報錯
以下是代碼,對下面代碼基本吃透,appium算是上手了
import time from appium import webdriver from selenium.webdriver.common.by import By # 判斷元素是否存在 def is_element_exist(element, timeout=3): count = 0 while count < timeout: souce = driver.page_source if element in souce: return True else: count += 1 time.sleep(1) return False desired_caps = { "platformName": "Android", # 操作系統 "deviceName": "UQG5T20610006585", # 設備 ID adb devices "platformVersion": "10", # 設備版本號 "appPackage": "com.tencent.mm", # app 包名 "appActivity": "com.tencent.mm.ui.LauncherUI", # app 啟動時主 Activity 'noReset': True, # 是否保留 session 信息,可以避免重新登錄 'autoLaunch Appium': True, 'automationName': 'UiAutomator1', 'unicodeKeyboard': True, # 使用 unicodeKeyboard 的編碼方式來發送字符串 'resetKeyboard': False # 將鍵盤給隱藏起來 } driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) print("微信啟動") # 上拉方法 def swipe_up(distance): # distance為滑動距離,time為滑動時間 size = driver.get_window_size() # print(size) x1 = 0.5 * size['width'] y1 = 0.8 * size['height'] y2 = (0.8 - distance) * size['height'] driver.swipe(x1, y1, x1, y2, duration=500) # 獲取通訊錄列表 def get_address_list(flag): if flag == True: driver.find_elements(By.ID, 'com.tencent.mm:id/f2i')[1].click() # 上滑 時間越短,划得屏幕越大 swipe_up(0.2) else: swipe_up(0.21) # 獲取昵稱(備注) address_list = driver.find_elements(By.ID, 'com.tencent.mm:id/hga') remarks = [] for address in address_list: remark = address.get_attribute("text") # 白名單 if remark != '個人微信名字' and ("微信團隊" not in remark) and ("文件傳輸助手" not in remark): remarks.append(remark) return remarks # 判斷是否被刪 def is_delete(remark, count): if count == "1": time.sleep(0.2) print('點擊微信搜索框') driver.find_element(By.ID, 'com.tencent.mm:id/gss').click() time.sleep(0.1) print('在搜索框輸入搜索信息') driver.find_element(By.ID, 'com.tencent.mm:id/cd6').send_keys(remark) time.sleep(0.1) print('點擊搜索到的好友') driver.find_element(By.ID, 'com.tencent.mm:id/kpx').click() time.sleep(0.1) print('功能按鈕展開') driver.find_element(By.ID, 'com.tencent.mm:id/b3q').click() time.sleep(0.1) print('點擊轉賬按鈕') driver.find_elements(By.ID, 'com.tencent.mm:id/ve')[5].click() time.sleep(0.1) print('跳轉,開始轉錢') driver.find_element(By.ID, 'com.tencent.mm:id/ffn').click() time.sleep(0.1) print('確認') driver.find_element(By.ID, 'com.tencent.mm:id/ffw').click() time.sleep(0.1) # 判斷是否被刪 is_exist = is_element_exist('com.tencent.mm:id/guv') if is_exist is True: return remark else: return False # 返回搜索框 def search_back(): time.sleep(0.1) driver.find_element(By.ID, 'com.tencent.mm:id/fz').click() time.sleep(0.1) driver.find_element(By.ID, 'com.tencent.mm:id/fz').click() time.sleep(0.1) # 清除搜索框,輸入下一個 driver.find_element(By.ID, 'com.tencent.mm:id/k1h').click() # 刪除把自己刪除的人 def del_person(nicks): print('點擊微信搜索框') driver.find_element(By.ID, 'com.tencent.mm:id/gss').click() for inx, val in enumerate(nicks): time.sleep(0.5) if inx == 0: print('在搜索框輸入搜索信息') driver.find_element(By.ID, 'com.tencent.mm:id/cd6').send_keys(val) else: time.sleep(1) print('點擊微信搜索框') driver.find_element(By.ID, 'com.tencent.mm:id/gss').click() print('在搜索框輸入搜索信息') time.sleep(0.5) driver.find_element(By.ID, 'com.tencent.mm:id/cd6').send_keys(val) time.sleep(0.5) print('點擊搜索到的人') driver.find_element(By.ID, 'com.tencent.mm:id/kpx').click() time.sleep(0.5) print('點擊聊天對話框右上角...') driver.find_element(By.ID, 'com.tencent.mm:id/en').click() time.sleep(1) print('點擊頭像') driver.find_element(By.ID, 'com.tencent.mm:id/iwj').click() time.sleep(1) print('點擊聯系人右上角...') driver.find_element(By.ID, 'com.tencent.mm:id/en').click() time.sleep(1) print('點擊刪除按鈕') driver.find_element(By.ID, 'com.tencent.mm:id/khu').click() time.sleep(1) print('點擊彈出框中的刪除') driver.find_element(By.ID, 'com.tencent.mm:id/gv3').click() if __name__ == '__main__': remarks = [] driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps) # 打開微信需要時間 time.sleep(5) remarks1 = get_address_list(True) remarks.extend(remarks1) while True: # 是否到了通訊錄末尾 is_end = is_element_exist('com.tencent.mm:id/bml') # time.sleep(0.2) remarks2 = get_address_list(False) remarks.extend(remarks2) if is_end == True: break remarks = set(remarks) print("通訊錄昵稱列表:", remarks) print("好友數目:", len(remarks)) time.sleep(1) dels = [] for inx, val in enumerate(remarks): rt = "" if inx == 0: rt = is_delete(val, "1") else: rt = is_delete(val, "") if rt is False: # 返回搜索框 driver.keyevent(4) search_back() # 被刪除 else: dels.append(rt) time.sleep(0.1) driver.find_element(By.ID, 'com.tencent.mm:id/gv3').click() search_back() print("刪除我的人:", dels) # 刪除刪了自己的人 del_person(dels)