偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Appium在Android UI測(cè)試中的應(yīng)用實(shí)踐

移動(dòng)開發(fā) Android
UI Automator Viewer 是 Android 官方的 UI 定位工具,位于 sdk/tools 下。運(yùn)行后會(huì)打開 viewer 界面。點(diǎn)擊獲取按鈕即可獲取當(dāng)前正在運(yùn)行的 Activity 的 UI 結(jié)構(gòu)。

 Android 測(cè)試工具與 Appium 簡(jiǎn)介

Appium 是一個(gè) C/S 架構(gòu)的,支持 Android/iOS Native, Hybrid 和 Mobile Web Apps 的測(cè)試框架,與測(cè)試程序通過 Selenum Webdriver 協(xié)議通訊。Webdriver 的好處是通過 HTTP RPC 的方式調(diào)用 Server 上的過程,編寫測(cè)試腳本不受語言的限制,無論是 Python, Java, NodeJS 均可以方便的編寫測(cè)試。本文中將使用 Python 進(jìn)行編程。

起因是因?yàn)槭袌?chǎng)部的同事拋來如下需求:批量添加一些微信好友。直接抓取請(qǐng)求進(jìn)行重放的方法是不靠譜的,微信與服務(wù)端的通訊均加密,Pass。考慮使用 xposed 等框架 hook 相關(guān)函數(shù)進(jìn)行操作。但是 xposed 需要越獄,且開發(fā)復(fù)雜,Pass。后來想到了使用 UI 測(cè)試工具進(jìn)行模擬操作,開發(fā)較為簡(jiǎn)單。

Android UI 測(cè)試工具有很多種,如 Monkey, UIAutomator, Selendroid, Robotium 等。其中 UIAutomator, Monkey, Selendroid 均為非侵入式的 UI 測(cè)試,也就是不需要修改源代碼,只要安裝了目標(biāo)程序就可以進(jìn)行測(cè)試。Robotium 需要與源碼一同編譯測(cè)試。Appium 實(shí)際上就是一個(gè)測(cè)試工具的統(tǒng)一調(diào)度軟件,將不同的非侵入式測(cè)試工具整合在一起,對(duì)外提供統(tǒng)一的 API。在 Android 2.3 以前的版本,Appium 會(huì)調(diào)用 Selendroid ,之后的版本會(huì)直接使用 UIAutomator,iOS 下使用 UIAutomation。Appium 還支持 FirefoxOS 的 UI 測(cè)試。

安裝 Appium

官網(wǎng)給出了命令行下的安裝方法。但實(shí)際上 Appium 有 GUI 版本,更適合在 Windows/MacOS 下使用。Windows 下需要安裝 .NET Framework。

  1. > brew install node      # get node.js 
  2. > npm install -g appium  # get appium 
  3. > npm install wd         # get appium client 
  4. > appium &               # start appium 
  5. > node your-appium-test.js 

Appium 需要依賴 Android SDK 編譯在手機(jī)端運(yùn)行的兩個(gè)插件,因此需要首先安裝相應(yīng)的 Android SDK 版本。這里直接使用了 Android Studio 中自帶的 SDK Manager。在 SDK Manager 中選擇和測(cè)試機(jī)相對(duì)應(yīng)的 SDK Platform 和較新的 Build-tools,如果需要使用模擬器測(cè)試還要裝對(duì)應(yīng)的 ARM/x86 System Image,以及 Intel HAXM Installer,用于加速 x86 虛擬機(jī)。Appium 使用 adb 來與目標(biāo)機(jī)器通訊,因此對(duì)于真機(jī)和模擬器操作幾乎都是相同的,如何建立模擬器在此不再贅述。

安裝完成后需要在 Appium GUI 中配置 Android SDK 目錄,隨后選擇 Android,點(diǎn)擊 Launch 就可以啟動(dòng) Appium Server。

Appium Server 默認(rèn)會(huì)監(jiān)聽 http://localhost:4723 ,用于 RPC 通訊。下面我們就可以打開熟悉的編程環(huán)境,編寫 UI 測(cè)試用例了。這里使用 Python 進(jìn)行編寫,需要先安裝 Appium 的 Python Client ,然后再 python 中使用 appium.webclient 就可以連接 Appium server了。

  1. pip install Appium-Python-Client 

使用 Appium 進(jìn)行 UI 控制

根據(jù)注釋修改相應(yīng)屬性后即可運(yùn)行測(cè)試。手機(jī)需要打開 ADB 調(diào)試,執(zhí)行完以下代碼后,Appium 會(huì)在手機(jī)上安裝 Appium Settings 和 Unlock 兩個(gè)程序,隨后微信會(huì)被啟動(dòng)。

  1. from appium import webdriver 
  2.  
  3. desired_caps = {} 
  4.  
  5. desired_caps['platformName'] = 'Android' #測(cè)試平臺(tái) 
  6.  
  7. desired_caps['platformVersion'] = '5.1' #平臺(tái)版本 
  8.  
  9. desired_caps['deviceName'] = 'm3_note' #設(shè)備名稱,多設(shè)備時(shí)需區(qū)分 
  10.  
  11. desired_caps['appPackage'] = 'com.tencent.mm' #app package名 
  12.  
  13. desired_caps['appActivity'] = '.ui.LauncherUI' #app默認(rèn)Activity 
  14.  
  15. dr = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) #啟動(dòng)Remote RPC 

Selenum Webdriver 使用了一種類似于 JS 中的 DOM 模型的方法來選擇頁(yè)面中的元素。dr 為當(dāng)前正在活動(dòng)的 activity 對(duì)象,可以使用 findElementByXXX 的方法來獲取 Activity 中的元素。所有 Element 后帶 s 的函數(shù),均獲得所有匹配的元素,不帶 s 的函數(shù)獲得***個(gè)匹配的元素。

查詢函數(shù)

1. findElement(s)ByName

在 Android 中基本沒用。Android UI 沒有 Name 這個(gè)屬性。有說可以使用 text 值獲取。但我并沒有成功

2. findElement(s)ByClassName

通過類名來獲取元素,用法如下:

  1. item_list = dr.find_elements_by_class_name("android.widget.LinearLayout"
  2. item_list[2].click() 

3. findElementById

通過 resource_id 來獲取元素,每個(gè) Activity 中都是***的,用法如下

  1. t = dr.find_element_by_id("com.tencent.mm:id/f7"
  2. t.send_keys(wechatId) 

4. findElement(s)ByAccessbiltiyId

在 Android 上 AccessbilityID 實(shí)際就是 contentDescription 。這個(gè)屬性是為了方便視力受損人士使用手機(jī)所設(shè)置。開啟 TTS 后系統(tǒng)會(huì)朗讀相關(guān)控件的 contentDescription。

5. findElement(s)ByXPath

通過 XML Path 描述來尋找元素。我沒有成功的獲取到,可能是 XPath 寫的有問題。

  1. s = dr.find_element_by_xpath("//android.widget.TextView[contains(@text,'搜索')]"
  2. s.click() 

6. findElementByAndroidUIAutomator

通過 UIAutomator 的選擇器來獲取元素。因?yàn)?Appium 在 Android 上實(shí)際是調(diào)用的 UIAutomator,所以可以通過 UIAutomator 的選擇器來選擇元素。

  1. el = dr.find_element_by_android_ui_automator("new UiSelector().text(\"搜索\")"
  2. el.click() 

操作函數(shù)

操作函數(shù)用于操作選定的元素,有很多,以下僅列舉幾個(gè),更多的請(qǐng)查閱手冊(cè)。

  • click
  • send_keys
  • clear

查詢函數(shù)返回的元素對(duì)象可以像 JS 中的 dom 元素一樣,繼續(xù)使用查詢函數(shù)來選定其子元素。用例如下。

  1. search = dr.find_element_by_id("com.tencent.mm:id/aqw").find_element_by_class_name("android.widget.RelativeLayout"
  2.  
  3. search.click() 

如何確定查詢規(guī)則

了解了相關(guān)的函數(shù)后,下面就應(yīng)對(duì) UI 進(jìn)行定位了。如果是自己團(tuán)隊(duì)開發(fā)的程序,推薦讓開發(fā)同學(xué)在所有的空間上都添加 resource_id 進(jìn)行絕對(duì)定位。如果碰到?jīng)]有談價(jià) resource_id 的元素,那就要使用別的辦法進(jìn)行定位了。

1. UI Automator Viewer

UI Automator Viewer 是 Android 官方的 UI 定位工具,位于 sdk/tools 下。運(yùn)行后會(huì)打開 viewer 界面。點(diǎn)擊獲取按鈕即可獲取當(dāng)前正在運(yùn)行的 Activity 的 UI 結(jié)構(gòu)。

2. AppiumDriver getPageSource

AppiumDriver(Client) 可以很方便的獲得當(dāng)前正在運(yùn)行的 Activity 的 UI 描述,隨后可根據(jù)返回的 XML 文檔來尋找元素。

  1. print dr.page_source 

確定元素位置后,即可根據(jù)前述的 Find 方法來查找/選擇元素

編寫完整的測(cè)試代碼

正確的獲取元素之后便可以獲取元素相關(guān)的信息,隨后使用各語言常用的測(cè)試框架編寫測(cè)試即可,如 Java 的 JUnit,Nodejs 的 Mocha 等。

這里我使用 Appium 主要是為了模擬用戶點(diǎn)擊添加微信好友,所以完整的程序并沒有使用到測(cè)試框架。相關(guān)的 UI 元素獲取/操作方法供大家參考。

  1. # coding:utf-8 
  2. from appium import webdriver 
  3. from time import sleep 
  4.  
  5.  
  6. def addFriend(dr, id, dryRun=False): 
  7.     succ = False 
  8.     wechatId = str(id) 
  9.     dr.find_element_by_accessibility_id(r"更多功能按鈕").click() 
  10.     item_list = dr.find_elements_by_class_name("android.widget.LinearLayout"
  11.     try: 
  12.         item_list[2].click() 
  13.     except
  14.         print "Error! in item list len" 
  15.         return succ 
  16.     el = dr.find_element_by_class_name("android.widget.ListView"
  17.     item_list = el.find_elements_by_class_name("android.widget.LinearLayout"
  18.     try: 
  19.         item_list[1].click() 
  20.     except
  21.         print "Error! in item list len" 
  22.         return succ 
  23.     t = dr.find_element_by_id("com.tencent.mm:id/f7"
  24.     t.send_keys(wechatId) 
  25.     search = dr.find_element_by_id("com.tencent.mm:id/aqw").find_element_by_class_name("android.widget.RelativeLayout"
  26.     search.click() 
  27.     try: 
  28.         freq = dr.find_element_by_id('com.tencent.mm:id/aqq'
  29.         assert freq.text == u"操作過于頻繁,請(qǐng)稍后再試。" 
  30.         print "Frequency too high! Sleep 300s" 
  31.         sleep(60) 
  32.         return succ 
  33.     except
  34.         pass 
  35.  
  36.     try: 
  37.         dr.find_element_by_id('com.tencent.mm:id/a8x').click() 
  38.         addBtn = dr.find_element_by_id('com.tencent.mm:id/eu'
  39.         if not dryRun: 
  40.             addBtn.click() 
  41.             succ = True 
  42.         print "Success Send Requests:" + wechatId 
  43.     except
  44.         print "No Such User Or Already a Friend:" + wechatId 
  45.  
  46.     while True
  47.         try: 
  48.             dr.find_element_by_id('com.tencent.mm:id/fb').click() 
  49.         except
  50.             try: 
  51.                 dr.find_element_by_id('com.tencent.mm:id/f4').click() 
  52.             except
  53.                 break 
  54.     return True 
  55.  
  56. def resetActivity(dr, desired_caps): 
  57.     dr.start_activity(desired_caps['appPackage'], desired_caps['appActivity']) 
  58.  
  59. desired_caps = {} 
  60. desired_caps['platformName'] = 'Android' 
  61. desired_caps['platformVersion'] = '5.1' 
  62. desired_caps['deviceName'] = 'm3_note' 
  63. desired_caps['appPackage'] = 'com.tencent.mm' 
  64. desired_caps['appActivity'] = '.ui.LauncherUI' 
  65. print "Trying connect to phone..." 
  66. dr = {} 
  67. try: 
  68.     dr = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) 
  69. except Exception, e: 
  70.     print "Cannot Connect to phone :", e 
  71.     exit() 
  72. print "Successfully connect to phone." 
  73. print "Reading friend list..." 
  74. friendList = [] 
  75. fp = open("friends.txt"
  76. line = fp.readline().strip() 
  77. while line: 
  78.     friendList.append(line) 
  79.     line = fp.readline().strip() 
  80. print "Finish reading friends. Total: " + str(len(friendList)) 
  81. print "Wait for Wechat's splash screen...." 
  82. for i in range(0, 10): 
  83.     print 10 - i 
  84.     sleep(1) 
  85. succ_list = [] 
  86. fail_list = [] 
  87. for i in friendList: 
  88.     try: 
  89.         succ = addFriend(dr, i, dryRun=False
  90.         if succ: 
  91.             succ_list.append(i) 
  92.         else
  93.             fail_list.append(i) 
  94.     except
  95.         fail_list.append(i) 
  96.         resetActivity(dr, desired_caps) 
  97.  
  98. print "Succeed List:" 
  99. print "\n".join(succ_list) 
  100. print "Failed List:" 
  101. print "\n".join(fail_list) 
  102.  
  103. dr.close() 

 【編輯推薦】

責(zé)任編輯:武曉燕 來源: segmentfault
相關(guān)推薦

2021-10-18 12:01:17

iOS自動(dòng)化測(cè)試Trip

2017-05-22 08:05:46

HBase阿里搜索實(shí)踐

2014-08-08 16:50:21

AB 測(cè)試安卓推送

2022-05-30 07:48:11

DevOps測(cè)試策略

2024-09-25 10:10:35

2012-07-09 10:13:06

ibmdw

2021-08-03 12:58:38

鴻蒙HarmonyOS應(yīng)用

2011-04-18 12:52:37

自動(dòng)化測(cè)試功能測(cè)試軟件測(cè)試

2024-04-07 07:53:12

SpringWeb技術(shù)WebSocket

2012-05-08 16:40:36

Android

2014-03-24 13:39:51

2019-11-26 18:00:59

系統(tǒng)運(yùn)維架構(gòu)

2024-06-04 07:29:13

2018-08-30 09:00:00

開源Apache Kafk數(shù)據(jù)流

2019-04-09 15:02:36

OpenResty騰訊游戲營(yíng)銷技術(shù)

2024-04-08 07:28:27

PiniaVue3狀態(tài)管理庫(kù)

2022-04-08 09:01:56

腳本Go應(yīng)用單元

2022-10-14 16:18:40

MobileNetAndroid端模型訓(xùn)練

2020-07-08 10:01:07

SDP網(wǎng)絡(luò)安全安全框架

2015-11-26 16:19:44

云智慧
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)