Appium | (轉)Appium使用教程


by?keeng2008@qq.com?2016-05-16

一、Appium介紹


????????Appium是一個開源的自動化測試工具,其支持iOS和安卓平臺上的原生的,基于移動瀏覽器的,混合的應用。

Appium 理念


Appium是基于以下的四個理念設計來滿足移動平臺測試自動化的要求的:

1)您不應該因為需要自動化測試您的應用而不得不以任何形式去重新編譯或者修改你的app

2)您不應該把自己固定在一門特定的語言和一個特定的框架上去實現和運行你的測試

3)當說到測試自動化APIs的時候,一個移動測試框架不應該做“重新發明輪子”的事情,

4)一個移動測試自動化框架應該是開源的,無論是在精神上,實際上,還是名義上!


使用Appium進行自動化測試有兩個好處


Appium在不同平臺中使用了標準的自動化APIs,所以在跨平臺時,不需要重新編譯或者修改自己的應用。

Appium支持Selenium WebDriver支持的所有語言,如java、Object-C、JavaScript、Php、Python、Ruby、C#、Clojure,或者Perl語言,更可以使用Selenium WebDriver的Api。Appium支持任何一種測試框架.Appium實現了真正的跨平臺自動化測試。(本文主要介紹Python的用法)

Appium架構


Appium 是一個用Node.js編寫的HTTP server,它創建、并管理多個 WebDriver sessions 來和不同平臺交互,如 iOS ,Android等等.?

Appium 開始一個測試后,就會在被測設備(手機)上啟動一個 server ,監聽來自 Appium server的指令. 每種平臺像 iOS 和Android都有不同的運行、和交互方式。所以Appium會用某個樁程序“侵入”該平臺,并接受指令,來完成測試用例的運行。

二、Appium環境搭建(Android)


首先需要準備


1) jdk(步驟不再啰嗦)

2) android SDK,下載地址:http://developer.android.com/sdk/index.html,下載sdk tools,可能需要FQ,提供一個國內下載地址:http://www.androiddevtools.cn/

3) appium,下載地址:http://appium.io/

4) nodejs,下載地址:https://nodejs.org/en/

5) python, 下載地址:https://www.python.org/, 下載3.X 的版本。

上述軟件都準備好后,則進入搭建步驟。

安裝、配置


將上述軟件依次安裝。

1) android sdk安裝完畢后,需要配置環境變量

新建ANDROID_HOME??? D:\ProgramFiles (x86)\Android\android-sdk

在PATH中添加:%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;

2) ?nodejs安裝完畢后,需要配置環境變量

在PATH中添加:D:\Program Files\nodejs;

3) appium安裝完畢后,需要配置環境變量

D:\Program Files (x86)\Appium\node_modules\.bin;

4) 配置好后,啟動cmd,

輸入node -v,查看node安裝版本

輸入appium-doctor檢查appium的安裝環境是否成功,如下圖:

5) 安裝Python,配置環境變量,如C:\Python27,檢查是否設置成功


三、開始例子(Python)


1) 啟動Appium

打開命令行,輸入appium, 顯示成功啟動:

2)連接Android手機(或者模擬器)

3)編寫客戶端代碼

創建文件hello_appium.py , 編輯內容:

#coding=utf-8

from appium import webdriver


desired_caps = {}

desired_caps['platformName'] = 'Android'

desired_caps['platformVersion'] = '4.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)

driver.find_element_by_name("1").click()

driver.find_element_by_name("5").click()

driver.find_element_by_name("9").click()

driver.find_element_by_name("9").click()

driver.find_element_by_name("5").click()

driver.find_element_by_name("+").click()

driver.find_element_by_name("6").click()

driver.find_element_by_name("=").click()

driver.quit()

4)運行

打開命令行,cd到E:\PythonTest\AppiumClientPython 中,運行 python?hello_appium.py, 正常情況可以看到手機按照代碼控制,打開計算器,逐個點擊按鈕完成計算。

四、Appium文檔


安裝應用后打開


import os

from appium import webdriver

APK_PATH = 'apk/ECloud-debug.apk'

COMMAND_EXECUTOR_URL = 'http://localhost:4723/wd/hub'


??? desired_caps = {}

??? desired_caps['platformName'] = 'Android'

??? desired_caps['platformVersion'] = '5.0'

??? desired_caps['deviceName'] = 'Android Emulator'

??? desired_caps['app'] = os.path.abspath(APK_PATH)


??? driver = webdriver.Remote(COMMAND_EXECUTOR_URL, desired_caps)

查找控件


1)通過名稱查找

btn = driver.find_element_by_name("+")

2)? 通過ID查找

start_btn =driver.find_element_by_id('com.cn21.ecloud:id/instruction_close_btn')

或 start_btn = driver.find_element_by_id('instruction_close_btn')

3)通過類名查找

child_text =parent.find_element_by_class_name('android.widget.TextView')

4)通過android_uiautomator查找

start_btn =driver.find_element_by_android_uiautomator('new UiSelector().clickable(true)')

以上find_element_by_XX 都是返回符合條件的第一個控件,如果要返回多個控件,可以調用 find_elements_by_XX, 返回的是一個list。

注意:如果找不到符合條件的控件,會拋出異常。

5)查找結點,不希望返回異常,寫個函數就行了

def find_element_by_id_no_except(driver, id):

??? element = None

??? try :

??????? element = driver.find_element_by_id(id)

??? except Exception,e:

??????? print Exception, ':', e

??? return element

模擬按鈕點擊


login_btn.click()

注意:有的點擊如果需要等待動畫、或者網絡請求,建議等待一會:

import time

time.sleep(2)? # 睡眠2秒

輸入框輸入文本


user_input.send_keys('123456')

注意:Android如果要正確輸入,需要把使用系統自帶的輸入法,第三方輸入法無法正確輸入。

模擬點擊返回鍵


driver.press_keycode(4)

其中按鈕的定義,由Android里的KeyEvent.java里定義的,所以其它的Android按鈕也是支持的。

關閉driver


driver.quit()

注意:一定要記得關閉driver, 否則下次連接的時候可能會出異常,因為Appium以為你上次未關閉,會創建Session失敗。

為了避免代碼出現異常而沒有關閉,可以在捕獲異常時再關閉。

滑動界面


下面的例子,演示點擊屏幕中間,并向上拉動(相當于查看列表下面的內容了)。

from appium.webdriver.common.touch_action import TouchAction

def test_scroll_down(driver):

??? screen = driver.get_window_size()

??? action = TouchAction(driver)

??? action.press(x=screen['width']/2,y=screen['height']/2)

??? action.move_to(x=0,y=-screen['height']/10)

??? action.release()

??? action.perform()


等等,怎么獲取界面的屬性來驗證正確性?

獲取界面屬性,控件屬性


1)獲取當前Activity名稱

activity = driver.current_activity

2) 獲取屏幕寬高

screen = driver.get_window_size()

3)獲取控件文本

mobile_name.get_attribute('text') 或者 mobile_name.text

4)獲取控件類名

mobile_name.get_attribute('className')

5)判斷控件是否顯示

mobile_name.is_displayed() 或者 mobile_name.get_attribute('displayed')

6)獲得控件位置

mobile_name.location

7)獲得控件大小

mobile_name.size

8)查找控件子結點

parent.find_elements_by_class_name('android.widget.TextView')

同樣:查找控件的其它方法,也適用于查找子結點。

對于交互后的驗證,無法驗證到具體的數據內容,可以驗證當前的Activity,或者文本,或者列表是否為空等等。

更多參考:http://blog.csdn.net/crisschan/article/details/50416860


五、結合單元測試框架編寫用例

Python自帶有unittest用于單元測試,其結構類似于JUnit。

一個測試類需要繼承于unittest.TestCase, 方法setUp 用于測試初始化,每個用例開始前都會調用,tearDown用于用例結束時調用,每個以test開始的函數被當成一個用例。

test_random.py

import random

import unittest


class TestSequenceFunctions(unittest.TestCase):


??? def setUp(self):

??????? self.seq = range(10)


??? def test_shuffle(self):

??????? # make sure the shuffled sequence does not lose any elements

??????? random.shuffle(self.seq)

??????? self.seq.sort()

??????? self.assertEqual(self.seq, range(10))


??????? # should raise an exception for an immutable sequence

??????? self.assertRaises(TypeError, random.shuffle, (1,2,3))


??? def test_choice(self):

??????? element = random.choice(self.seq)

??????? self.assertTrue(element in self.seq)


??? def test_sample(self):

??????? with self.assertRaises(ValueError):

??????????? random.sample(self.seq, 20)

??????? for element in random.sample(self.seq, 5):

??????????? self.assertTrue(element not in self.seq)


if __name__ == '__main__':

??? unittest.main(verbosity=2)


運行此測試: python test_random.py 可以查看測試的結果

上面結果顯示,有2個用例測試通過,1個用例不通過。

可以在一個目錄下寫多個以test開頭的測試文件,然后通過以下命令運行所有測試類:

python -m unittest discover . -v


六、完整例子


測試登陸登出功能


test_ecloud_login_logout.py

#coding=utf-8

#?

測試天翼云登陸登出功能

#?

用例1:快速登陸,驗證登陸后的Activity為MainPageActivity

# 用例2:普通登陸,輸入用戶名密碼,驗證登陸后的Activity為MainPageActivity

# 用例3:快速登陸后注銷,驗證注銷后的Activity為LoginActivity

import?unittest

import?appium_ecloud

import?appium_util

from?appium?import?webdriver

import?os

class?LoginLogoutTest(unittest.TestCase):

?##

?def?setUp(self):

?#print('Installing ...')

?desired_caps = {}

desired_caps['platformName'] =?'Android'

?desired_caps['platformVersion'] =?'5.0'

?desired_caps['deviceName'] =?'Android Emulator'

?desired_caps['app'] = os.path.abspath(appium_ecloud.APK_PATH)

?self.driver = webdriver.Remote(appium_util.COMMAND_EXECUTOR_URL, desired_caps)


?def?tearDown(self):

?self.driver.quit()


?def?test_FastLogin(self):

appium_ecloud.agree_document(self.driver)

appium_ecloud.quick_login(self.driver)

?self.assertTrue(self.driver.current_activity.endswith('MainPageActivity'))


?def?test_SlowLigin(self):

appium_ecloud.agree_document(self.driver)

appium_ecloud.slow_login(self.driver)

?self.assertTrue(self.driver.current_activity.endswith('MainPageActivity'))


?def?test_Logout(self):

appium_ecloud.agree_document(self.driver)

appium_ecloud.quick_login(self.driver)

?if?(self.driver.current_activity.endswith('MainPageActivity')):

appium_ecloud.test_logout(self.driver)

?self.assertTrue(self.driver.current_activity.endswith('LoginActivity'))

if?__name__ ==?'__main__':

unittest.main(verbosity=2)


自動亂點測試崩潰的情況


auto_test_ecloud.py

#coding=utf-8

import?random

import?time

import?traceback

import?appium_ecloud

def?auto_interact(driver):

activity = driver.current_activity

?#?一定的機率滑動,返回鍵,點擊

?rate = random.random()

?if?rate <?0.1:

?print?activity +?' Scroll Down'

?appium_ecloud.test_scroll_down(driver)

?elif?rate <?0.2:

?print?activity +?' Scroll Up'

?appium_ecloud.test_scroll_up(driver)

?elif?rate <?0.3:

?print?activity +?' Key Back'

?driver.press_keycode(4)

?else:

btn_list = driver.find_elements_by_android_uiautomator('new UiSelector().clickable(true)')

?if?(len(btn_list) >?0):

index = random.randint(0,?len(btn_list) -?1)

?print?activity +?' Click Button index = %d'?% (index,)

btn_list[index].click()

def?main():

driver =?None

?try:

driver = appium_ecloud.install_app()

time.sleep(appium_ecloud.LONG_WAIT_TIME)

appium_ecloud.agree_document(driver)

appium_ecloud.quick_login(driver)

step =?0

while?step <?100:

?if?(driver.current_activity.endswith('LoginActivity')):

appium_ecloud.test_login(driver)

?elif?(driver.current_activity.endswith('.Launcher')):

driver.background_app(1)

driver.launch_app()

?else:

auto_interact(driver)

time.sleep(appium_ecloud.CLICK_WAIT_TIME)

step +=?1

#?正常退出

?driver.quit()

?except?Exception, e:

?print?Exception,?":", e

traceback.print_exc()

?#?異常退出

?if?(driver !=?None):

driver.quit()

if?__name__ ==?'__main__':

?for?i?in?range(20000):

?try:

main()

?except?Exception, e:

?print?Exception,?":", e

traceback.print_exc()

注:為了更方便的編寫python代碼,推薦使用PyCharm IDE,編輯代碼跟Java一樣方便。

七、參考資料:


1)官網?http://appium.io/index.html

2)appium/python-client使用文檔https://github.com/appium/python-client

3)搭建appium的android環境http://www.cnblogs.com/qiaoyeye/p/5131382.html

4)Appium移動自動化測試(四)http://www.cnblogs.com/fnng/p/4579152.html

5)AppiumPython API?http://blog.csdn.net/crisschan/article/details/50416860

6)appium常用方法總結?http://www.cnblogs.com/fanxiaojuan/p/4882676.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370