轉:http://www.yangyanxing.com/article/1266.htmlhtml
下面這段介紹來自於appium的官網。java
Appium is an open-source tool you can use to automate mobile native, mobile web, and mobile hybrid applications on iOS and Android platforms. 「Mobile native apps」 are those written using the iOS or Android SDKs. 「Mobile web apps」 are web apps accessed using a mobile browser (Appium supports Safari on iOS and Chrome on Android). 「Mobile hybrid apps」 have a native wrapper around a 「webview」 – a native control that enables interaction with web content. Projects like Phonegap, for example, make it easy to build apps using web technologies that are then bundled into a native wrapper – these are hybrid apps.node
Importantly, Appium is 「cross-platform」: it allows you to write tests against multiple platforms (iOS, Android), using the same API. This enables a large or total amount of code reuse between iOS and Android testsuites.python
咱們能夠從上面的介紹裏得到這樣的一些信息:linux
appium的哲學android
Appium was designed to meet mobile automation needs according to a certain philosophy. The key points of this philosophy can be stated as 4 requirements:ios
- You shouldn’t have to recompile your app or modify it in any way in order to automate it.
- You shouldn’t be locked into a specific language or framework to write and run your tests.
- A mobile automation framework shouldn’t reinvent the wheel when it comes to automation APIs.
- A mobile automation framework should be open source, in spirit and practice as well as in name!
appium的設計哲學是這樣的:git
We meet requirement #2 by wrapping the vendor-provided frameworks in one API, theWebDriver API. WebDriver (aka 「Selenium WebDriver」) specifies a client-server protocol (known as theJSON Wire Protocol). Given this client-server architecture, a client written in any language can be used to send the appropriate HTTP requests to the server. There are already clients written in every popular programming language. This also means that you’re free to use whatever test runner and test framework you want; the client libraries are simply HTTP clients and can be mixed into your code any way you please. In other words, Appium & WebDriver clients are not technically 「test frameworks」 – they are 「automation libraries」. You can manage your test environment any way you like!github
We meet requirement #3 in the same way: WebDriver has become the de facto standard for automating web browsers, and is a W3C Working Draft. Why do something totally different for mobile? Instead we have extended the protocol with extra API methods useful for mobile automation.web
It should be obvious that requirement #4 is a given – you’re reading this because Appium is open source.
首先,爲了可以實現哲學裏描述的第2條,也就是不該該讓移動端自動化測試限定在某種語言和某個具體的框架;也就是說任何人均可以使用本身最熟悉最順手的語言以及框架來作移動端自動化測試;appium選擇了client-server的設計模式。只要client可以發送http請求給server,那麼的話client用什麼語言來實現都是能夠的,這就是appium及webdriver如何作到支持多語言的;
其次,爲了可以實現不要爲了移動端的自動化測試而從新發明輪子,從新寫一套驚天動地的api;也就是說webdriver協議裏的api已經夠好了,拿來改進一下就能夠了;這個思想,appium擴展了webdriver的協議,沒有本身從新去實現一套。這樣的好處是之前的webdriver api可以直接被繼承過來,之前的webdriver各類語言的binding均可以拿來就用,省去了爲每種語言開發一個client的工做量;
最後appium固然是開源的,這也實現了哲學思想裏的最後一點。
appium的核心實際上是一個暴露了一系列REST API的server。
這個server的功能其實很簡單:監聽一個端口,而後接收由client發送來的command。翻譯這些command,把這些command轉成移動設備能夠理解的形式發送給移動設備,而後移動設備執行完這些command後把執行結果返回給appium server,appium server再把執行結果返回給client。
在這裏client其實就是發起command的設備,通常來講就是咱們代碼執行的機器,執行appium測試代碼的機器。狹義點理解,能夠把client理解成是代碼,這些代碼能夠是java/ruby/python/js的,只要它實現了webdriver標準協議就能夠。
這樣的設計思想帶來了一些好處:
session就是一個會話,在webdriver/appium,你的全部工做永遠都是在session start後才能夠進行的。通常來講,經過POST /session這個URL,而後傳入Desired Capabilities就能夠開啓session了。
開啓session後,會返回一個全局惟一的session id,之後幾乎全部的請求都必須帶上這個session id,由於這個seesion id表明了你所打開的瀏覽器或者是移動設備的模擬器。
進一步思考一下,因爲session id是全局惟一,那麼在同一臺機器上啓動多個session就變成了可能,這也就是selenium gird所依賴的具體理論根據。
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
Desired Capabilities
Desired Capabilities攜帶了一些配置信息。從本質上講,這個東東是key-value形式的對象。你能夠理解成是java裏的map,python裏的字典,ruby裏的hash以及js裏的json對象。實際上Desired Capabilities在傳輸時就是json對象。
Desired Capabilities最重要的做用是告訴server本次測試的上下文。此次是要進行瀏覽器測試仍是移動端測試?若是是移動端測試的話是測試android仍是ios,若是測試android的話那麼咱們要測試哪一個app? server的這些疑問Desired Capabilities都必須給予解答,不然server不買帳,天然就沒法完成移動app或者是瀏覽器的啓動。
具體例子以下:
For example, we might set the
platformName
capability toiOS
to tell Appium that we want an iOS session, rather than an Android one. Or we might set thesafariAllowPopups
capability totrue
in order to ensure that, during a Safari automation session, we’re allowed to use JavaScript to open up new windows. See the capabilities doc for the complete list of capabilities available for Appium
這就是每次咱們在命令行用appium命令打開的東西。
因爲原生的webdriver api是爲web端設計的,所以在移動端用起來會有點不三不四。appium官方提供了一套appium client,涵蓋多種語言ruby/java/python,在我看來ruby client是實現最好的。在測試的時候,通常要使用這些client庫去替換原生的webdriver庫。這實際上不是替換,算是client對原生webdriver進行了一些移動端的擴展,加入了一些方便的方法,好比swipe之類,appium client讓咱們能夠更方便的寫出可讀性更好的測試用例。
appium server的GUI版本,前者用在osx上,後者是windows上。可視化、不須要裝node,能夠看app的UI結構是這個東東的賣點。
appium的哲學裏有一條就是不從新發明輪子。一樣,官方已經有明確的安裝步驟了,所以在這裏純屬搬磚。
感謝testerhome的辛勤翻譯。
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
若是你在windows上安裝appium,你無法使用預編譯專用於OS X的.app文件,你也將不能測試IOS apps,由於appium依賴OS X專用的庫來支持IOS測試。這意味着你只能經過在mac上來運行IOS的app測試。這點限制挺大。
ANDROID_HOME
系統變量爲你的Android SDK路徑,並把tools platform-tools兩個目錄加入到系統的Path路徑裏。由於這裏麪包含有一些執行命令JAVA_HOME
變量爲你的JDK目錄。如今,你已經下載安裝了全部的依賴,開始運行 reset.bat
要在windows上運行測試用例,你須要先啓動Android模擬器或者鏈接上一個API Level17以上的android真機。 而後在命令行運行appium node .
config.ini
中有一個配置項爲hw.battery=yes
出於對官方文檔的尊重,我按照原文翻譯,以下介紹個人安裝心得。官方提到的一些工具,其實並不須要安裝。 下面介紹我已經測試過的安裝和使用過程
二、使用npm安裝appium,npm install -g appium
注意:在某些狀況下,appium安裝的時候並不會把appium的路徑放進系統的PATH裏,這時候須要手工去加一下。
啓動appium,直接運行appium 便可。
經過npm install -g appium
來更新appium便可
appium client是對webdriver原生api的一些擴展和封裝。它能夠幫助咱們更容易的寫出用例,寫出更好懂的用例。
appium client是配合原生的webdriver來使用的,所以兩者必須配合使用缺一不可。
從本節開始,教程的內容將涵蓋3個語言,ruby/python/java。
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
ruby的appium client叫作appium lib,爲何是這樣就不解釋了,總之是歷史緣由。
首先update rubygem和bundler(說老實話,真的不須要,但官方文檔上這麼寫)
gem update --system ; gem update bundler
而後使用gem安裝
gem uninstall -aIx appium_lib ;(這個也不是必須的) gem install --no-rdoc --no-ri appium_lib
推薦使用pip安裝
pip install Appium-Python-Client
固然了也能夠在Pipy上下載源碼安裝
tar -xvf Appium-Python-Client-X.X.tar.gz(windows上用7zip能夠解壓) cd Appium-Python-Client-X.X python setup.py install
最後,也能夠經過github安裝(要git客戶端)
git clone git@github.com:appium/python-client.git cd python-client python setup.py install
java的話用maven安裝就能夠了
<dependency> <groupId>io.appium</groupId> <artifactId>java-client</artifactId> <version>1.3.0</version> </dependency>
固然了,也能夠本身下載jar包,請自行選擇最新版本。
appium client擴展了原生的webdriver client方法
下面以java代碼爲例,簡單過一下appium client提供的適合移動端使用的新方法
新增的locator
這些方法主要覆蓋了3大類:
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
下一節咱們開始介紹使用appium啓動android模擬器
通常狀況下,咱們都從命令行啓動appium。
windows下,dos命令窗口輸入
appium
若是該命令報錯,那麼請重裝appium
npm install -g appium
若是安裝出錯,請自行更換npm源。
npm -g --registry http://registry.cnpmjs.org install appium
而後請打開android的模擬器,若是沒有請新建一個虛擬設備。請自行解除設備鎖定(手動把屏幕解鎖了),以防萬一。
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
下面的代碼以啓動android原生的計算器程序爲例
require 'appium_lib' caps = { caps: { platformName: 'Android', appActivity: '.Calculator', appPackage: 'com.android.calculator2' }, appium_lib: { sauce_username: nil, sauce_access_key: nil } } driver = Appium::Driver.new(caps).start_driver
討論:能夠看出ruby lib裏面的Appium::Driver類實際上就是原生的webdriver類的子類,固然了,因爲ruby語法靈活,也可使用monkey patch來實現相似功能。
from appium import webdriver desired_caps = {} desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '4.2' desired_caps['deviceName'] = 'Android Emulator' desired_caps['appPackage'] = 'com.android.calculator2' desired_caps['appActivity'] = '.Calculator' driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
討論:webdriver.Remote實際上就是原生webdriver的子類,另外Remote()構造函數的第一個參數中須要顯示指定appium server監聽的端口
新建java項目時候,請注意將selenium-webdriver以及appium client的jar包導入
import io.appium.java_client.AppiumDriver; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(CapabilityType.BROWSER_NAME, "");//這句不是必須的 capabilities.setCapability("deviceName","Android Emulator"); capabilities.setCapability("platformVersion", "4.4"); capabilities.setCapability("platformName","Android"); capabilities.setCapability("appPackage", "com.android.calculator2"); capabilities.setCapability("appActivity", ".Calculator"); AppiumDriver driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
討論:AppiumDrvier是原生webdriver的子類。
在這裏咱們能夠看到,新建driver的時候必需要指定一個DesiredCapabilities 對象,該對象到底是何方神聖,咱們下一節會仔細講解。
Desired Capabilities在啓動session的時候是必須提供的。
Desired Capabilities本質上是key value的對象,它告訴appium server這樣一些事情:
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
iOS
, Android
, orFirefoxOS?
iPhone Simulator
, iPad Simulator
, iPhone Retina 4-inch
, Android Emulator
, Galaxy S4
, etc...本文主要討論android平臺的appium測試方法和技巧,所以在這裏就不列出ios設備特定的屬性了。
更多信息請參考官方文檔
在這裏咱們發現,咱們常常要獲取app的package和activity名字,那麼有什麼工具可讓咱們方便的獲取到這些信息呢?下一節講回答這個問題。
該文件位於your_andriod_sdk_pathtools下面。以乙醇的機器爲例,其位於E:adt-bundle-windows-x86-20131030sdktools下。
該工具能夠幫咱們找到android控件的content-description,爲之後的find_element_by_accessibility_id
定位方法作參數使用。
關於什麼是content-description,能夠參考官方文檔。
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
好,露個臉。
該文件位於your_andriod_sdk_pathtools下面。以乙醇的機器爲例,其位於E:adt-bundle-windows-x86-20131030sdktools下。
該工具主要用來查看控件的屬性,好比resource id,class name等。
該工具也可查看被測app的appPackage(Desired Capabilities中使用)。
爆照。
好了,是否是感受還缺了點什麼呢?
確實如此,被測app的appActivity怎麼獲取呢?
下一講咱們詳細講解如何獲取被測app的appActivity。
有時候在appium的Desired Capabilities中須要指定被測app的appActivity,下面的方法可能會對你有所幫助。
若有你有待測項目的源碼,那麼直接查看源碼就好。若是沒有,那麼請聯繫有源碼的同窗,這是推薦方法。
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
若是你沒有代碼,那麼能夠反編譯該app。
這裏將用到2個工具,分別是dex2jar和jd-gui。你能夠在這裏下載目前爲止的最新版本以及示例apk。
咱們以工具包裏的ContactManager.apk爲例,簡單介紹一下反編譯的流程。
d2j-dex2jar.bat path_toclasses.dex
在當前文件夾下獲得classes-dex2jar.jar;
嗯,好了,能夠盡情欣賞了。上圖。
上圖所示的ContactManager就是待測app的main activity。
參考testerhome的這個帖子
使用log查看大法(嗯,windows上沒grep不幸福,好在有powershell的Select-String,能夠拿來勉強一用),直接搬磚。
a、啓動待測apk
b、開啓日誌輸出:adb logcat>D:/log.txt
c、關閉日誌輸出:ctrl+cd、查看日誌
找尋:
Displayed com.mm.android.hsy/.ui.LoginActivity: +3s859ms appPackage = com.mm.android.hsy appActivity = .ui.LoginActivity
好了,準備活動作的差很少了。下一節乙醇帶你們進行控件定位之旅。
狹義上講,UI級的自動化測試就是讓機器代替人去點來點去的過程。
但機器去點什麼(點上面仍是點左邊),怎麼點(是長按仍是輕觸),這些東西是必須由代碼的編寫者所指示清楚的。
控件定位就是解決機器點什麼的問題的。
通常說來,咱們能夠這樣告訴機器:去點登錄按鈕。
機器很笨,它並不知道什麼是登錄按鈕。由於登錄按鈕是天然語言的描述。
若是你讓一我的去點登錄按鈕,那麼他其實也是要通過一系列的腦補之後才能夠作這件事的。
這個腦補的過程還原以下:
這個必定是個按鈕
這個按鈕必定在被測的應用上
這個按鈕大概上面有登錄這個文字信息
嗯,還真有一個,那麼點吧。
這就是人探索性測試的一個簡單過程。通常來講,若是你給出的信息不太充分,人類仍是能夠經過一系列的探索性思惟去理解你的描述的。這個屬於心理學的問題,不展開解釋。
可是機器並非人,若是你給出的描述不精確的話,機器是不會自發性的進行探索和腦補的。
所以控件定位就是精確的描述控件特徵並告訴機器的過程。
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
控件的特徵就是控件的屬性,咱們能夠經過上一講中的uiautomatorviewer去獲取。
在appium的定位世界裏,下面這些方法是能夠爲咱們使用的。也就是說,咱們經過下面幾個約定好的方式,按照webdriver和appium的DSL(自行搜索並理解)進行控件特徵的描述和定位。
繼承自webdriver的方法,也就是經過這3個特徵能夠定位控件
由Mobile JSON Wire Protocol 協議中定義的方法,更適合移動設備上的控件定位
-ios uiautomation
: a string corresponding to a recursive element search using the UIAutomation library (iOS-only)-android uiautomator
: a string corresponding to a recursive element search using the UiAutomator Api (Android-only)accessibility id
: a string corresponding to a recursive element search using the Id/Name that the native Accessibility options utilize.在appium 的client對Mobile JSON Wire Protocol中定義的方法進行了封裝,使其調用起來更加方便
find_element :accessibility_id, 'Animation' find_elements :accessibility_id, 'Animation' find_element :uiautomator, 'new UiSelector().clickable(true)' find_elements :uiautomator, 'new UiSelector().clickable(true)'
固然了,你也可使用原生的webdriver方法
find_element id: 'resource_id'
另外,ruby lib裏提供了一些很是好用的簡便方法來進行控件的定位,好寫,好讀。
更多請看這裏
el = self.driver.find_element_by_android_uiautomator('new UiSelector().description("Animation")') self.assertIsNotNone(el) els = self.driver.find_elements_by_android_uiautomator('new UiSelector().clickable(true)') self.assertIsInstance(els, list) el = self.driver.find_element_by_accessibility_id('Animation') self.assertIsNotNone(el) els = self.driver.find_elements_by_accessibility_id('Animation') self.assertIsInstance(els, list)
總的來講就是在driver裏增長了
等方法
前面也講過了,新增了這些方法
findElementByAccessibilityId() findElementsByAccessibilityId() findElementByIosUIAutomation() findElementsByIosUIAutomation() findElementByAndroidUIAutomator() findElementsByAndroidUIAutomator()
討論:從上面能夠看出來,python 和 java client對移動端控件定位的封裝是比較初級的。ruby lib中封裝了不少方便和簡潔的方法,所以能夠看出,使用ruby lib是優於python和java的選擇。固然,若是忽略性能的話。
下一節咱們開始具體看下如何用resource id去定位控件。
上一節乙醇帶你們瞭解了appium的定位策略。實際上appium的控件定位方式是徹底遵照webdriver的mobile擴展協議的。
這一節將分享一下如何使用resource id來定位android策略。
什麼是resource id,這個不屬於本文的範疇,你們能夠點這裏瞭解。
咱們能夠有兩種方式來使用resource id進行定位:
從上面的代碼片斷能夠看到,使用 find_element_by_id 的方式進行定位是最簡便的。
那麼怎麼獲取控件的resource id呢,使用uiautomatorviewer就能夠了。具體方法以下圖所示。
如今就以上圖所示的android原生計算器程序爲例,看一下每種語言是如何實現點擊【9】這個按鈕的。
點擊計算器上的【9】這個按鈕。該按鈕的id是com.android.calculator2:id/digit6
。先甜後苦,從ruby開始。
本文版權歸乙醇全部,歡迎轉載,但請註明做者與出處,嚴禁用於任何商業用途
require 'appium_lib' caps = { caps: { platformName: 'Android', appActivity: '.Calculator', appPackage: 'com.android.calculator2' }, appium_lib: { sauce_username: nil, sauce_access_key: nil, debug: true} } dr = Appium::Driver.new(caps).start_driver dr.find_element(id: 'com.android.calculator2:id/digit9').click
#coding:utf-8 from appium import webdriver from time import sleep desired_caps = {} desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '4.4' desired_caps['deviceName'] = 'Android Emulator' desired_caps['app'] = 'Calculator.apk' desired_caps['appPackage'] = 'com.android.calculator2' desired_caps['appActivity'] = '.Calculator' dr = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) sleep(3) dr.find_element_by_id('com.android.calculator2:id/digit9').click()
//新建一個FindById類位於info.itest.www package下面 package info.itest.www; import io.appium.java_client.AppiumDriver; import java.net.MalformedURLException; import java.net.URL; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; public class FindById { public static void main(String args[]) throws MalformedURLException { DesiredCapabilities cap = new DesiredCapabilities(); cap.setCapability(CapabilityType.BROWSER_NAME, ""); cap.setCapability("platformName", "Android"); cap.setCapability("deviceName", "Android Emulator"); cap.setCapability("platformVersion", "4.4"); cap.setCapability("appPackage", "com.android.calculator2"); cap.setCapability("appActivity", ".Calculator"); AppiumDriver dr = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), cap); dr.findElement(By.id("com.android.calculator2:id/digit9")).click(); } }
若是讀者對webdriver很熟悉的話,那麼掌握這個方法是很是簡單的。若是對webdriver不熟悉,那麼能夠參考乙醇的webdriver實用指南,先學習一下webdriver的基礎知識。
這一節咱們寫了一些腳本去進行控件定位,在實際的項目中,這些沒有任何斷言的腳本是基本上沒法完成測試用例的功能的。
先賣個關子,下下一節乙醇將會帶你們寫第一個appium的測試用例。
那麼下一節咱們將學習如何使用class name進行定位。