Appium是一個跨平臺移動端自動化測試工具,能夠很是便捷地爲iOS和Android平臺建立自動化測試用例。它能夠模擬App內部的各類操做,如點擊、滑動、文本輸入等,只要咱們手工操做的動做Appium均可以完成。在前面咱們瞭解過Selenium,它是一個網頁端的自動化測試工具。Appium實際上繼承了Selenium,Appium也是利用WebDriver來實現App的自動化測試。對iOS設備來講,Appium使用UIAutomation來實現驅動。對於Android來講,它使用UiAutomator和Selendroid來實現驅動。
html
Appium至關於一個服務器,咱們能夠向Appium發送一些操做指令,Appium就會根據不一樣的指令對移動設備進行驅動,完成不一樣的動做。python
對於爬蟲來講,咱們用Selenium來抓取JavaScript渲染的頁面,可見便可爬。Appium一樣也能夠,用Appium來作App爬蟲不失爲一個好的選擇。android
下面咱們來了解Appium的基本使用方法。ios
咱們以Android平臺的微信爲例來演示Appium啓動和操做App的方法,主要目的是瞭解利用Appium進行自動化測試的流程以及相關API的用法。
git
請確保PC已經安裝好Appium、Android開發環境和Python版本的Appium API。另外,Android手機安裝好微信App。
github
Appium啓動App的方式有兩種:一種是用Appium內置的驅動器來打開App,另外一種是利用Python程序實現此操做。下面咱們分別進行說明。
web
首先打開Appium,啓動界面以下圖所示。bash
直接點擊Start Server按鈕便可啓動Appium的服務,至關於開啓了一個Appium服務器。咱們能夠經過Appium內置的驅動或Python代碼向Appium的服務器發送一系列操做指令,Appium就會根據不一樣的指令對移動設備進行驅動,完成不一樣的動做。啓動後運行界面以下圖所示。服務器
Appium運行以後正在監聽4723端口。咱們能夠向此端口對應的服務接口發送操做指令,此頁面就會顯示這個過程的操做日誌。微信
將Android手機經過數據線和運行Appium的PC相連,同時打開USB調試功能,確保PC能夠鏈接到手機。
能夠輸入adb命令來測試鏈接狀況,以下所示:
adb devices -l複製代碼
若是出現相似以下結果,這就說明PC已經正確鏈接手機。
List of devices attached
2da42ac0 device usb:336592896X product:leo model:MI_NOTE_Pro device:leo複製代碼
model
是設備的名稱,就是後文須要用到的deviceName
變量。我使用的是小米Note頂配版,因此此處名稱爲MI_NOTE_Pro。
若是提示找不到adb
命令,請檢查Android開發環境和環境變量是否配置成功。若是能夠成功調用adb
命令但不顯示設備信息,請檢查手機和PC的鏈接狀況。
接下來用Appium內置的驅動器打開App,點擊Appium中的Start New Session按鈕,以下圖所示。
這時會出現一個配置頁面,以下圖所示。
須要配置啓動App時的Desired Capabilities參數,它們分別是platformName
、deviceName
、appPackage
、appActivity
。
platformName
:它是平臺名稱,須要區分Android或iOS,此處填寫Android。
deviceName
:它是設備名稱,此處是手機的具體類型。
appPackage
:它是App程序包名。
appActivity
:它是入口Activity名,這裏一般須要以 . 開頭。
在當前配置頁面的左下角也有配置參數的相關說明,連接是https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md。
咱們在Appium中加入上面4個配置,以下圖所示。
點擊保存按鈕,保存下來,咱們之後能夠繼續使用這個配置。
點擊右下角的Start Session按鈕,便可啓動Android手機上的微信App並進入到啓動頁面。同時PC上會彈出一個調試窗口,從這個窗口咱們能夠預覽當前手機頁面,並能夠查看頁面的源碼,以下圖所示。
點擊左欄中屏幕的某個元素,如選中登陸按鈕,它就會高亮顯示。這時中間欄就顯示了當前選中的按鈕對應的源代碼,右欄則顯示了該元素的基本信息,如元素的id、class、text等,以及能夠執行的操做,如Tap、Send Keys、Clear,以下圖所示。
點擊中間欄最上方的第三個錄製按鈕,Appium會開始錄製操做動做,這時咱們在窗口中操做App的行爲都會被記錄下來,Recorder處能夠自動生成對應語言的代碼。例如,咱們點擊錄製按鈕,而後選中App中的登陸按鈕,點擊Tap操做,即模擬了按鈕點擊功能,這時手機和窗口的App都會跳轉到登陸頁面,同時中間欄會顯示此動做對應的代碼,以下圖所示。
接下來選中左側的手機號文本框,點擊Send Keys,對話框就會彈出。輸入手機號,點擊Send Keys,便可完成文本的輸入,以下圖所示。
咱們能夠在此頁面點擊不一樣的動做按鈕,便可實現對App的控制,同時Recorder部分也能夠生成對應的Python代碼。
下面咱們看看使用Python代碼驅動App的方法。首先須要在代碼中指定一個Appium Server,而這個Server在剛纔打開Appium的時候就已經開啓了,是在4723端口上運行的,配置以下所示:
server = 'http://localhost:4723/wd/hub'複製代碼
用字典來配置Desired Capabilities參數,代碼以下所示:
desired_caps = {
'platformName': 'Android',
'deviceName': 'MI_NOTE_Pro',
'appPackage': 'com.tencent.mm',
'appActivity': '.ui.LauncherUI'
}複製代碼
新建一個Session,這相似點擊Appium內置驅動的Start Session按鈕相同的功能,代碼實現以下所示:
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Remote(server, desired_caps)複製代碼
配置完成後運行,就能夠啓動微信App了。可是如今僅僅是能夠啓動App,尚未作任何動做。
再用代碼來模擬剛纔演示的兩個動做:一個是點擊「登陸」按鈕,一個是輸入手機號。
看看剛纔Appium內置驅動器內的Recorder錄製生成的Python代碼,自動生成的代碼很是累贅,例如點擊「登陸」按鈕的代碼以下所示:
el1 = driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.View/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.Button[1]")
el1.click()複製代碼
這段代碼的XPath選擇器路徑太長,選擇方式沒有那麼科學,獲取元素時也沒有設置等待,極可能會有超時異常。因此咱們修改一下,將其修改成經過ID查找元素,設置延時等待,兩次操做的代碼改寫以下所示:
wait = WebDriverWait(driver, 30)
login = wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/cjk')))
login.click()
phone = wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/h2')))
phone.set_text('18888888888')複製代碼
綜上所述,完整的代碼以下所示:
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
server = 'http://localhost:4723/wd/hub'
desired_caps = {
'platformName': 'Android',
'deviceName': 'MI_NOTE_Pro',
'appPackage': 'com.tencent.mm',
'appActivity': '.ui.LauncherUI'
}
driver = webdriver.Remote(server, desired_caps)
wait = WebDriverWait(driver, 30)
login = wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/cjk')))
login.click()
phone = wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/h2')))
phone.set_text('18888888888')複製代碼
必定要從新鏈接手機,再運行此代碼,這時便可觀察到手機上首先彈出了微信歡迎頁面,而後模擬點擊登陸按鈕、輸入手機號,操做完成。這樣咱們就成功使用Python代碼實現了App的操做。
接下來看看使用代碼如何操做App、總結相關API的用法。這裏使用的Python庫爲AppiumPythonClient,其GitHub地址爲https://github.com/appium/python-client,此庫繼承自Selenium,使用方法與Selenium有不少共同之處。
須要配置Desired Capabilities參數,完整的配置說明能夠參考https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md。通常來講,配置幾個基本參數便可,以下所示:
from appium import webdriver
server = 'http://localhost:4723/wd/hub'
desired_caps = {
'platformName': 'Android',
'deviceName': 'MI_NOTE_Pro',
'appPackage': 'com.tencent.mm',
'appActivity': '.ui.LauncherUI'
}
driver = webdriver.Remote(server, desired_caps)複製代碼
這裏配置了啓動微信App的Desired Capabilities,這樣Appnium就會自動查找手機上的包名和入口類,而後將其啓動。包名和入口類的名稱能夠在安裝包中的AndroidManifest.xml文件獲取。
若是要打開的App沒有事先在手機上安裝,咱們能夠直接指定App參數爲安裝包所在路徑,這樣程序啓動時就會自動向手機安裝並啓動App,以下所示:
from appium import webdriver
server = 'http://localhost:4723/wd/hub'
desired_caps = {
'platformName': 'Android',
'deviceName': 'MI_NOTE_Pro',
'app': './weixin.apk'
}
driver = webdriver.Remote(server, desired_caps)複製代碼
程序啓動的時候就會尋找PC當前路徑下的APK安裝包,而後將其安裝到手機中並啓動。
咱們可使用Selenium中通用的查找方法來實現元素的查找,以下所示:
el = driver.find_element_by_id('com.tencent.mm:id/cjk')複製代碼
在Selenium中,其餘查找元素的方法一樣適用,在此再也不贅述。
在Android平臺上,咱們還可使用UIAutomator來進行元素選擇,以下所示:
el = self.driver.find_element_by_android_uiautomator('new UiSelector().description("Animation")')
els = self.driver.find_elements_by_android_uiautomator('new UiSelector().clickable(true)')複製代碼
在iOS平臺上,咱們可使用UIAutomation來進行元素選擇,以下所示:
el = self.driver.find_element_by_ios_uiautomation('.elements()[0]')
els = self.driver.find_elements_by_ios_uiautomation('.elements()')複製代碼
還可使用iOS Predicates來進行元素選擇,以下所示:
el = self.driver.find_element_by_ios_predicate('wdName == "Buttons"')
els = self.driver.find_elements_by_ios_predicate('wdValue == "SearchBar" AND isWDDivisible == 1')複製代碼
也可使用iOS Class Chain來進行選擇,以下所示:
el = self.driver.find_element_by_ios_class_chain('XCUIElementTypeWindow/XCUIElementTypeButton[3]')
els = self.driver.find_elements_by_ios_class_chain('XCUIElementTypeWindow/XCUIElementTypeButton')複製代碼
可是此種方法只適用於XCUITest驅動,具體能夠參考:https://github.com/appium/appium-xcuitest-driver。
點擊可使用tap()
方法,該方法能夠模擬手指點擊(最多五個手指),可設置按時長短(毫秒),代碼以下所示:
tap(self, positions, duration=None)複製代碼
其中後兩個參數以下。
positions
:它是點擊的位置組成的列表。
duration
:它是點擊持續時間。
實例以下所示:
driver.tap([(100, 20), (100, 60), (100, 100)], 500)複製代碼
這樣就能夠模擬點擊屏幕的某幾個點。
對於某個元素如按鈕來講,咱們能夠直接調用cilck()方法實現模擬點擊,實例以下所示:
button = find_element_by_id('com.tencent.mm:id/btn')
button.click()複製代碼
可使用scroll()
方法模擬屏幕滾動,用法以下所示:
scroll(self, origin_el, destination_el)複製代碼
能夠實現從元素origin_el
滾動至元素destination_el
。
它的後兩個參數以下。
original_el
:它是被操做的元素。
destination_el
:它是目標元素。
實例以下所示:
driver.scroll(el1,el2)複製代碼
可使用swipe()
模擬從A點滑動到B點,用法以下所示:
swipe(self, start_x, start_y, end_x, end_y, duration=None)複製代碼
後面幾個參數說明以下。
start_x
:它是開始位置的橫座標。
start_y
:它是開始位置的縱座標。
end_x
:它是終止位置的橫座標。
end_y
:它是終止位置的縱座標。
duration
:它是持續時間,單位是毫秒。
實例以下所示:
driver.swipe(100, 100, 100, 400, 5000)複製代碼
這樣能夠實如今5s時間內,由(100, 100)滑動到 (100, 400)。
可使用flick()
方法模擬從A點快速滑動到B點,用法以下所示:
flick(self, start_x, start_y, end_x, end_y)複製代碼
幾個參數說明以下。
start_x
:它是開始位置的橫座標。
start_y
:它是開始位置的縱座標。
end_x
:它是終止位置的橫座標。
end_y
:它是終止位置的縱座標。
實例以下所示:
driver.flick(100, 100, 100, 400)複製代碼
可使用drag_and_drop()
將某個元素拖動到另外一個目標元素上,用法以下所示:
drag_and_drop(self, origin_el, destination_el)複製代碼
能夠實現將元素origin_el
拖曳至元素destination_el
。
兩個參數說明以下。
original_el
:它是被拖曳的元素。
destination_el
:它是目標元素。
實例以下所示:
driver.drag_and_drop(el1, el2)複製代碼
可使用set_text()
方法實現文本輸入,以下所示:
el = find_element_by_id('com.tencent.mm:id/cjk')
el.set_text('Hello')複製代碼
與Selenium中的ActionChains相似,Appium中的TouchAction可支持的方法有tap()
、press()
、long_press()
、release()
、move_to()
、wait()
、cancel()
等,實例以下所示:
el = self.driver.find_element_by_accessibility_id('Animation')
action = TouchAction(self.driver)
action.tap(el).perform()複製代碼
首先選中一個元素,而後利用TouchAction實現點擊操做。
若是想要實現拖動操做,能夠用以下方式:
els = self.driver.find_elements_by_class_name('listView')
a1 = TouchAction()
a1.press(els[0]).move_to(x=10, y=0).move_to(x=10, y=-75).move_to(x=10, y=-600).release()
a2 = TouchAction()
a2.press(els[1]).move_to(x=10, y=10).move_to(x=10, y=-300).move_to(x=10, y=-600).release()複製代碼
利用以上API,咱們就能夠完成絕大部分操做。更多的API操做能夠參考:https://testerhome.com/topics/3711。
本節中,咱們主要了解了Appium的操做App的基本用法,以及經常使用API的用法。
本資源首發於崔慶才的我的博客靜覓: Python3網絡爬蟲開發實戰教程 | 靜覓
如想了解更多爬蟲資訊,請關注個人我的微信公衆號:進擊的Coder
weixin.qq.com/r/5zsjOyvEZ… (二維碼自動識別)