Appium入門級知識點彙總

整理了網上的資源,希望對大家有幫助吧,不喜勿噴

一、Appium簡介

Appium是一個移動端的自動化框架,是跨平臺的。可用於IOS和Android以及firefox的操作系統。 
• 原生應用是指用android或ios的sdk編寫的應用; 
• 移動網頁web應用是指網頁應用,類似於ios中safari應用或者Chrome應用或者類瀏覽器的應用; 
• 混合應用是指一種包裹webview的應用。

1.1 Appium架構原理

Appium是在手機操作系統自帶的測試框架基礎上實現的,Android4.2版本以上使用的是UIAutomator,Android4.2及以下使用的是基於Android Instrumentation框架實現的自動化測試工具;iOS是基於iOS自帶的UI自動化工具UIAutomation實現的。

Appium由客戶端和服務器組成,客戶端與服務器通過JSON Wire Protocol進行通信。下圖簡單的介紹了各部分。

Appium-架構

Appium Server: 
Appium server使用node.js寫的http服務器,遵守REST風格。主要作用是接受從Appium客戶端發起的連接,監聽客戶端發送來的命令,將命令發送給Bootstrap.jar(或Bootstrap.js)執行,並將執行結果通過HTTP應答反饋給Appium客戶端。

Bootstrap.jar: 
在Android手機上運行的一個應用程序,它在手機上扮演TCP服務器的角色。當Appium需要運行命令時,Appium服務器會與Bootstrap.jar建立TCP通信,Bootstrap.jar負責運行測試。

Appium Clients: 
是一個擴展WebDriver 協議的庫,負責與Appium服務端建立連接,並將腳本的指令發動到服務端。支持多種語言。

Session: 
Appium的客戶端於服務端之間進行通信都必須在一個Session的上下文中進行。客戶端在發起通信的時候,會首先發動一個叫“Desired Capabilities”的JSON對象給服務器。服務器收到該數據後,會創建一個Session並將Session ID返回給客戶端。客戶端可以用此ID發送命令。

Desired Capabilities: 
是一組設置的鍵值對的集合,主要用於通知Appium服務器建立需要的Session,其中一些設置可以在Appium運行過程中改變Appium服務器的運行行爲。

1.2 Appium優缺點

優點:

  • 支持多種應用程序的測試
  • 支持使用多種語言來編寫測試腳本
  • 被測試的應用程序不需要特殊的編譯
  • Appium支持應用之間跳轉的測試

缺點:

  • 由於服務端運行在電腦上,該工具必須連接電腦纔可以運行
  • 只能用於UI的自動化測試,在很多情況下的測試驗證只能通過驗證界面來進行

1.3 WebDriver

Appium採用底層驅動商提供統一的WebDriver API,它和Selenium有着千絲萬縷的聯繫,很多方法的使用都很相似,可以參考筆者之前寫過的Selenium文章。

Selenium自動化測試-入門 
Selenium自動化測試-unittest單元測試框架使用

二、Appium環境搭建

2.1 安裝Appium運行環境

  1. Android運行環境 
    安裝Android SDK後,並將其加入到系統環境變量中。
  2. 安裝Python
  3. 安裝Node.js 
    是爲了用命令行的方式啓動Appium。
  4. 安裝Appium服務器 
    可以從此網站下載安裝http://appium.io/

2.2 Appium服務器啓動

打開Appium軟件後,點擊右上角的三角形,可以打開啓動服務器,如下所示:

appium運行

如果輸出類似如下信息,沒有錯誤提示,就表示啓動成功了。

> Launching Appium server with command: C:\tools\Appium\node.exe lib\server\main.js --address 127.0.0.1 --port 4723 --platform-name Android --platform-version 23 --automation-name Appium --device-name "8c28b78c" --log-no-color
> info: Welcome to Appium v1.4.16 (REV ae6877eff263066b26328d457bd285c0cc62430d)
> info: Appium REST http interface listener started on 127.0.0.1:4723
> info: [debug] Non-default server args: {"address":"127.0.0.1","logNoColors":true,"deviceName":"8c28b78c","platformName":"Android","platformVersion":"23","automationName":"Appium"}
> info: Console LogLevel: debug
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

啓動之後,可以在瀏覽器裏面訪問http://localhost:4723/看看是否有反應,如果正常啓動的話,肯定是有反應的。我們需要在設置中改變一些設置,也可以將界面中的log信息導出到文件中,便於我們處理。

appium setting

appium setting2

三、編寫腳本前的準備

3.1 查看頁面元素

Native APP: 
我們可以使用Android SDK安裝目錄下的uiautomatorviewer來查看APP的頁面元素,~\sdk\tools\uiautomatorviewer.bat

appium uiautomator

也可以使用Appium inspector來查看,但是沒有uiautomatorviewer那麼好用。

appium inspector

含有webview的APP: 
可以通過Chrome的DevTools來獲取,在Chrome中輸入chrome://inspect/#devices後,如果有連接上的設備,可以點擊inspect進入查看頁面。

devtools

不過,有時通過這種方法是無法獲取到頁面的,原因可能是被測程序的WebView沒有開debug模式等。這時我們可以獲取當前頁面的URL然後通過Chrome或Firefox等來訪問並且查看元素。

3.2 相關文檔

這個網站上說明了Appium的方方面面,如設計理念、各個平臺的安裝、腳本編寫等等。http://appium.io/slate/cn/master/?python#about-appium

通過appium在GitHub上的介紹我們可以獲取編寫腳本的一些方法,這裏給出的是Python語言的鏈接。https://github.com/appium/python-client

3.3 簡單示例

用Python寫Appium的腳本時,只需以下幾步即可以構造一個基本的用例,如下代碼片斷所示:

        #構造Desired Capabilities
        desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['platformVersion'] = '6.0.1'
        desired_caps['deviceName'] = '8c28b78c'
        desired_caps['appPackage'] = 'com.ss.android.article.news'
        desired_caps['appActivity'] = '.activity.SplashActivity'
        driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

        #1.獲取元素
        videoBtn = driver.find_element_by_name("視頻")

        #2.操作元素
        videoBtn.click()

        #3.結果驗證

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

我們首先需要構造一個Desired Capabilities,設置一些參數,用它來連接到APP中,然後就是進行UI自動化操作的標準3步了。

  1. 獲取頁面控件
  2. 操作控件
  3. 控件信息驗證

對這三步很熟悉了之後,我們再在這個基礎上做一些封裝,使得腳本更加健壯,可維護性更高。接下來按照以上幾步來一步步做吧。

四、Desired Capabilities說明

Desired Capabilities就是一組設置,這些設置可以讓測試腳本控制Appium的運行行爲。下面對這些設置做一個簡單的說明。從其官方網站我們可以得到全面的信息,網址爲:http://appium.io/slate/en/master/?java#appium-server-capabilities

4.1 與Appium服務器相關的

Capability 是否爲必填項 描述
automationName Appium使用的測試引擎 Appium(默認)
platformName 被測設備的系統平臺 iOS,Android,Firefox OS,null(默認)
platformVersion 手機系統版本 如6.6.1,null(默認)
deviceName 測試設備類型(測試Android時被忽略) null(默認)
app 指向APP安裝文件,Android中如果設置了appActivity和appPackage,則此會被忽略 null(默認)
browserName 手機網頁測試時瀏覽器的名稱 設置爲Safari在測iOS和Chrome時,設置爲Browser在測Android時
newCommandTimeout Appium服務器等待Appium客戶端發送新消息的時間,單位爲s 60s(默認)
language (僅模擬器使用)設置模擬器的語言 null(默認)
locale (僅模擬器使用)設置模擬器的使用國家 null(默認)
udid (僅真機使用)測試設備的ID 在多臺設備與同一臺電腦連接時必須指定
orientation (僅模擬器使用)屏幕方向 LANDSCAPE,PORTRAIT,null(默認)
autoWebview 直接切換到WebView上下文 false(默認),true
noReset 在一個Session開始前不重置被測程序的狀態 false(默認),true
fullReset 完全重置(Android通過卸載程序的方式),Session完成後會卸載程序 false(默認),true

~

4.2 僅對Android測試有效的設置

Capability 是否爲必填項 描述
appActivity 被測APP啓動的Activity名稱 如.MainActivity
appPackage 被測APP的包名 例如:com.example.android.myApp
deviceReadyTimeout 等待設備ready的超時時間 5s(默認)
ignoreUnimportantViews 會忽略一些控件,加快運行 false(默認),true
disableAndroidWatchers 只針對基於UIAutomator的測試有效,不會監控ANR和Crash,這將較少CPU消耗 false(默認),true
unicodeKeyboard 是否支持Unicode的鍵盤,如果輸入中文,設置爲是 false(默認),true
resetKeyboard 測試結束後是否恢復鍵盤,爲正常的手機鍵盤 false(默認),true
androidScreenshotPath 截圖存放的目錄 /data/local/tmp(默認)

~

關於Android測試的Capability非常的多,以上只是其中常用的一部分。還有iOS相關的沒有在這裏敘述了,有興趣的可以訪問前面給出的官網地址去查看。

五、獲取控件

5.1 Native APP

API 方法描述
find_element_by_id(self,id) 通過控件的resource id來查找控件
find_element_by_name(self,name) Native APP中,name就是控件的Text
find_element_by_class_name(self,name) 控件的class name,網頁測試也可以用此
find_element_by_accessibility_id(self,id) 控件的accessibility_id就是Content Description
find_element_by_android_uiautomator(self,uia_string) 根據UIAutomator的語法查找控件,是WebDriver在兼容Appium時才新加的語法

~

頁面中同一個ID的控件可能不止一個,最常見的就是列表項。find_element_by_id是查找頁面中第一個ID爲指定參數的控件,find_elements_by_id是查找頁面中所有ID爲指定參數的控件,返回一個控件列表。其他的查找方法類似。

5.2 Web&Hybrid APP

API 方法描述
find_element_by_xpath(self,xpath) 通過控件的xpath來查找控件
find_element_by_css_selector(self,css_selector) 通過控件的css_selector來查找控件
find_element_by_link_text(self,link_text) 通過鏈接的text來查找控件
find_element_by_partiallink_text(self,link_text) 通過鏈接的部分文本來查找控件
find_element_by_tag_name(self,tag_name) 通過網頁元素的Tag查找控件

~

這一部分的控件查找和Selenium中的幾乎一樣,可以查看筆者之前的相關文章。

5.3 獲取控件舉例

appium find1

下面代碼片段爲獲取圖中底部tab的視頻按鈕的兩種方法。第一種用到了name屬性,先找到其父控件,進一步縮小範圍,因爲頁面中可能在其他地方也有相同的name。第二種是用find_elements系列的方法,再拿到列表中的第2項,因爲下方的幾個控件id都是相同的。

self.driver.find_element_by_id("android:id/tabs").find_element_by_name("視頻").click()           self.driver.find_elements_by_id("com.ss.android.article.news:id/b5e")[1].click()
  • 1

對於一些找不到方法去定位的元素怎麼辦呢?首先想到的就是座標定位,爲了兼容更多的機型,可以用相對座標或者距離元素的位置來定位。更高端的方法就是可以採用圖像識別來確定要定位的元素,從而進行點擊,可以參考這篇文章。http://tmq.qq.com/2017/02/test_guide/

六、操作控件

6.1 獲取控件信息(部分)

API 方法描述
text(self) 獲取控件顯示的文本信息
is_enabled(self) 判斷是否可用了,可用返回true
is_selected(self) 是否被選中了,是的話返回true
id_displayed(self) 判斷控件是否顯示,是的話返回true
get_attribute(self,name) 獲取控件某項信息,如element.get_attribute(“displayed”)等同於id_displayed方法
parent(self) 返回控件的父控件,返回值爲一個控件對象

6.2 手勢操作(部分)

主要有點擊、滑動、拖拽、放縮等常用的操作。

API 方法描述
click(self) 點擊控件
clear(self) 清楚文本框控件的文本
send_keys(self,*value) 發送文本到控件中
tap(self,positions,duration=None) positions是一個列表,每個列表是一個二元組最多可以同時點擊5個點;duration爲時間長短,給參數的話則是長按操作
swipe(self,start_x,start_y,end_x,end_y,duration=None) 從一點滑動到另一點,時長爲毫秒
flick(self,start_x,start_y,end_x,end_y) 兩點快速的滑動
scroll(self,origin_ele,destination_ele) 從origin_ele控件滾動到destination_ele控件
drag_and_drop(self,origin_ele,destination_ele) 把origin_ele控件拖拽到destination_ele控件的位置
pinch(self,element=None,percent=200,steps=50) 在指定控件上執行縮小操作,默認縮放比例爲2,分50步完成
zoom(self,element=None,percent=200,steps=50) 在指定控件上執行放大操作,默認縮放比例爲2,分50步完成

6.3 系統操作API(部分)

系統操作用於模擬硬件操作、設置網絡環境、獲取系統信息等,下表簡單的介紹一下常用的方法。

API 方法描述
launch_app(self) 啓動Capability中指定的APP
is_app_installed(self,package_name) 判斷應用程序是否安裝
install_app(self,app_path) 安裝APP,app_path指的是電腦上的apk路徑
close_app(self) 如果Capability指定的APP在運行,則關閉它
background_app(self,seconds) 將APP放到後臺運行一段時間
reset(self) 重置當前被測APP到初始狀態
current_activity(self) 獲取當前正在顯示的Activity
start_activity(self,app_package,app_activity,**opts) 啓動某個Activity
pull_file(self,path) 拉取手機上的一個文件,並以base64格式編碼返回數據,path爲手機文件路徑
pull_folder(self,path) 拉取手機上的一個文件夾,打包後以base64格式編碼返回數據,path爲手機上的文件夾路徑
push_file(self,path,base64data) 將一個base64編碼格式的文件從電腦推送到手機上的路徑path上
press_keycode(self,keycode,metastate=None) 模擬發送一個硬件碼到手機,如返回等
open_notification(self) 打開通知欄
network_connection(self) 返回當前網絡連接的類型
set_network_connection(self,connectionType) 設置網絡,值爲:0 未設置,1 飛行模式,2 WiFi only, 4 Data only, 6 WiFi& Data
get_screenshot_as_file(self,filename) 截圖並保存在電腦上,filename爲路徑及截圖名稱
save_screenshot(filename) 截圖並保存在電腦上,filename爲路徑及截圖名稱

七、控件信息驗證

這裏我們要說的是查找並操作控件後,怎麼確定我們的操作起了作用。在實際的測試中也把它叫做檢查點,檢查點的劃分和驗證是UI自動化中的一個重點也是難點。常用的有以下方法:

  1. 判斷某個控件是否顯示(操作之後新出現的控件)
  2. 判斷某個控件是否被選中
  3. 判斷某個開關控件是否處於check狀態
  4. 判斷某個控件是否enabled
  5. 截圖之後和正確的進行比對 

可以將以上判斷的方式進行封裝,便於我們在if語句和assert中使用。關於截圖對比的方式,首先要有正確的操作截圖,然後再進行對比得出結論看看是否一致,會涉及一些算法相關的知識。

八、常見問題

8.1 A new session could not be created

有一次在執行的過程中,發現輸出了以下錯誤;

selenium.common.exceptions.WebDriverException: Message: A new session could not be created. (Original error: An unknown server-side error occurred while processing the command. (Original error: unknown error: com.android.chrome is not installed on device 8c28b78c
  (Driver info: chromedriver=2.18.343845 (73dd713ba7fbfb73cbb514e62641d8c96a94682a),platform=Windows NT 10.0 x86_64)))
  • 1
  • 2

可以發現主要的錯誤應該是com.android.chrome is not installed on device,這個看起來應該是chrome瀏覽器的手機端,我們可以嘗試安裝它。但是,我記得手機上一直都沒有安裝過這個,最後又檢查了一下,發現原來是打開了Appium設置中的Browser,關閉此即可。

appium setting

然而,除了這個原因有可能是別的原因,我們要具體分析錯誤輸出,還可以做一些事情來來降低這種情況的發生:

  1. 在初始化的setUp()方法中調用ADB命令強制關閉被測應用一次;
  2. 添加–session-override選項,命令行中或者Appium界面中;
  3. 在tearDown()方法中,關閉Appium的session,清理環境。

8.2 Permission to start activity denied.

在使用start_activity()方法來啓動另一個APP時,有時會遇到如下錯誤:

selenium.common.exceptions.WebDriverException: Message: Unable to launch the app: Error: Permission to start activity denied.

這時可以看到我們沒有權限打開這一個Activity,通常是因爲此Activity在清單文件裏面沒添加Android:exported=”true”,exported屬性就是設置是否允許activity被其它程序調用的。所以我們需要從啓動頁Activity打開如下所示。這在一些情況下可能會有點麻煩。

app_package='com.gotokeep.keep'
app_activity='.activity.SplashActivity'
self.driver.start_activity(app_package,app_activity)
  • 1
  • 2
  • 3

還有一種錯誤是找不到要打開的Activity:

elenium.common.exceptions.WebDriverException: Message: Unable to launch the app: Error: Activity used to start app doesn’t exist or cannot be launched! Make sure it exists and is a launchable activity

檢查Activity是否存在,並且路徑是否填寫正確。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章