軟件測試教程 自動化測試appium篇
本課程主要講解自動化測試工具appium。
下面以android app測試為例桶癣,講解appium的基本使用方法
appium概念
appium安裝配置
一個測試樣例
Appium 概念
Appium是一個移動端的自動化框架连锯,可用于測試原生應(yīng)用祟滴,移動網(wǎng)頁應(yīng)用和混合型應(yīng)用抖剿,且是跨平臺的。可用于IOS和Android以及firefox的操作系統(tǒng)。
Appium使用WebDriver的json wire協(xié)議,來驅(qū)動Apple系統(tǒng)的UIAutomation庫缺亮、Android系統(tǒng)的UIAutomator框架疼约。
原生的應(yīng)用是指用android或ios的sdk編寫的應(yīng)用瀑踢。原生應(yīng)用程序看起來(外觀)和運行起來(性能)是最佳的。
移動網(wǎng)頁應(yīng)用是指網(wǎng)頁應(yīng)用,HTML5應(yīng)用程序使用標(biāo)準(zhǔn)的Web技術(shù),通常是HTML5唉韭、JavaScript和CSS吼句。
混合應(yīng)用程序讓開發(fā)人員可以把HTML5應(yīng)用程序嵌入到一個細(xì)薄的原生容器里面志于,集原生應(yīng)用程序和HTML5應(yīng)用程序的優(yōu)點(及缺點)于一體橘荠。
appium選擇了client-server的設(shè)計模式。
通過上面一張圖簡單展示了appium的工具原理。
客戶端/服務(wù)器架構(gòu)
Appium 的核心是暴露 REST API 的網(wǎng)絡(luò)服務(wù)器屈嗤。它接受來自客戶端的連接,監(jiān)聽命令并在移動設(shè)備上執(zhí)行洪囤,答復(fù)表示執(zhí)行結(jié)果的 HTTP 響應(yīng)冲簿」┝叮客戶端/服務(wù)器架構(gòu)實際給予了許多可能性:我們可以使用任何有 http 客戶端 API 的語言編寫我們的測試代碼盒蟆,不過選一個Appium 客戶端程序庫 使用更容易或颊。我們可以把服務(wù)器放在另一臺機器上,而不是執(zhí)行測試的機器续徽。
會話(session)
自動化始終在一個會話的上下文中執(zhí)行愉耙,這些客戶端程序庫以各自的方式發(fā)起與服務(wù)器的會話搞坝,但都以發(fā)給服務(wù)器一個 POST /session
請求結(jié)束,請求中包含一個被稱作 'desired capabilities' 的 JSON 對象极谊。這時服務(wù)器就會開啟這個自動化會話囱桨,并返回一個用于發(fā)送后續(xù)命令的會話 ID们童。
Desired Capabilities
Desired capabilities 是一些發(fā)送給 Appium 服務(wù)器的鍵值對集合 (比如 map 或 hash),告訴服務(wù)器我們想要啟動什么類型的自動化會話椎瘟。也有各種可以在自動化運行時修改服務(wù)器行為的 capabilities泼舱。例如等缀,我們可以把 platformName
capability 設(shè)置為 iOS
,告訴 Appium 我們想要 iOS 會話娇昙,而不是 Android 或者 Windows 會話窒舟。我們也可以設(shè)置 safariAllowPopups
capability 為 true
尺锚,確保我們在 Safari 自動化會話中可以使用 javascript 打開新窗口。有關(guān) Appium capabilities 的完整列表,請參閱 capabilities doc 捺弦。
Appium 服務(wù)器
Appium 是用 Node.js 寫的服務(wù)器。它可以從源碼構(gòu)建安裝或者從 NPM 直接安裝:
$ npm install -g appium
$ appium
Appium 客戶端
有多個客戶端程序庫(Java茴丰、Ruby困介、Python、PHP,铃诬、JavaScript 和 C# 的)支持 Appium 對 WebDriver 協(xié)議的擴(kuò)展严蓖,你需要用這些客戶端程序庫代替通常的 WebDriver 客戶端。在這里瀏覽所有程序庫的列表氧急。
Appium.app, Appium.exe
有 Appium 服務(wù)器的圖形界面包裝器可以下載颗胡。它們打包了 Appium 服務(wù)器運行需要的所有東西,所以你不需要為 Node 而煩惱吩坝。它們還提供一個 Inspector 使你可以查看你應(yīng)用的層級結(jié)構(gòu)毒姨,這在寫測試時很方便。
appium安裝配置
Appium-desktop安裝
原來版本的appium-server不再維護(hù)钉寝,新的工具 是Appium-desktop弧呐。
官網(wǎng)地址:http://appium.io/,下載合適的版本
windows平臺下載:appium-desktop-setup-1.4.0.exe
雙擊進(jìn)行安裝嵌纲,安裝過程不需要任何設(shè)置
安裝完成桌面會生成一個紫色的appium 圖標(biāo)俘枫,雙擊打開。
默認(rèn)顯示監(jiān)控的 host 和 port 逮走,這和 Appium-Server中是一致的鸠蚪。點擊 “Start Server V 1.7.2” 按鈕啟動服務(wù)。
注意:不能在瀏覽器中設(shè)置代理
Traceback (most recent call last):
File "C:\Users\liujiey\Desktop\test.py", line 20, in setUp
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
File "build\bdist.win32\egg\appium\webdriver\webdriver.py", line 36, in __init__
super(WebDriver, self).__init__(command_executor, desired_capabilities, browser_profile, proxy, keep_alive)
File "C:\Python27\lib\site-packages\selenium-2.48.0-py2.7.egg\selenium\webdriver\remote\webdriver.py", line 87, in __init__
self.start_session(desired_capabilities, browser_profile)
File "C:\Python27\lib\site-packages\selenium-2.48.0-py2.7.egg\selenium\webdriver\remote\webdriver.py", line 141, in start_session
'desiredCapabilities': desired_capabilities,
File "C:\Python27\lib\site-packages\selenium-2.48.0-py2.7.egg\selenium\webdriver\remote\webdriver.py", line 199, in execute
response = self.command_executor.execute(driver_command, params)
File "C:\Python27\lib\site-packages\selenium-2.48.0-py2.7.egg\selenium\webdriver\remote\remote_connection.py", line 395, in execute
return self._request(command_info[0], url, body=data)
File "C:\Python27\lib\site-packages\selenium-2.48.0-py2.7.egg\selenium\webdriver\remote\remote_connection.py", line 463, in _request
resp = opener.open(request, timeout=self._timeout)
File "C:\Python27\lib\urllib2.py", line 394, in open
response = self._open(req, data)
File "C:\Python27\lib\urllib2.py", line 412, in _open
'_open', req)
File "C:\Python27\lib\urllib2.py", line 372, in _call_chain
result = func(*args)
File "C:\Python27\lib\urllib2.py", line 1199, in http_open
return self.do_open(httplib.HTTPConnection, req)
File "C:\Python27\lib\urllib2.py", line 1170, in do_open
r = h.getresponse(buffering=True)
File "C:\Python27\lib\httplib.py", line 1027, in getresponse
response.begin()
File "C:\Python27\lib\httplib.py", line 407, in begin
version, status, reason = self._read_status()
File "C:\Python27\lib\httplib.py", line 371, in _read_status
raise BadStatusLine(line)
BadStatusLine: ''
安裝 python-client
python-client 的項目名稱叫:Appium-Python-Client。
安裝方式:pip install Appium-Python-Client
該項目依賴selenium
在python中測試: from appium import webdriver茅信,導(dǎo)入成功說明安裝完成
如果使用其他語言盾舌,則安裝其他語言的client
安裝 JDK
app sdk的運行需要JDK的支持,因此需要先安裝JDK
需要配置JAVA_HOME蘸鲸,并設(shè)置path路徑
安裝 Android SDK
進(jìn)行模擬器測試時妖谴,需要SDK的支持。如果真機測試的話酌摇,會用到platform-tool膝舅,例如adb等工具。因此建議安裝SDK窑多。
Android SDK 下載地址:
http://tools.android-studio.org/index.php/sdk
選擇對應(yīng)平臺版本下載仍稀,這里選擇:
安裝SDK:
1、雙擊進(jìn)行安裝
2怯伊、安裝過程中會檢查JDK
3琳轿、安裝完畢后會提示運行SDK manager
4、除默認(rèn)勾選的之外耿芹,選擇需要下載支持的版本崭篡,例如Android 7.0,Android 6.0等吧秕,這里選擇Android 4.2.2進(jìn)行下載
設(shè)置環(huán)境變量:
下面設(shè)置環(huán)境變量:
“我的電腦” 右鍵菜單 —> 屬性 —> 高級 —> 環(huán)境變量 —> 系統(tǒng)變量 —> 新建…
變量名 | 變量值 |
---|---|
ANDROID_HOME | D:\android\Android\sdk |
找到 path 變量名—> “編輯” 添加:
變量名 | 變量值 |
---|---|
PATH | ;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools; |
創(chuàng)建模擬器:
1琉闪、雙擊 AVD Manage.exe 啟動AVD管理器。
2砸彬、點擊 “Create…” 按鈕颠毙,創(chuàng)建Android虛擬機。
3砂碉、不要選擇超過電腦屏幕分辨率的Device蛀蜜。Target選擇SDK下載的版本增蹭,Skin選擇no skin即可滴某,點擊 “OK” 創(chuàng)建完成。
4滋迈、在 AVD Manage 工具中選中創(chuàng)建的Android虛擬機霎奢,點擊 “Start…” 按鈕啟動。
使用Intel atom模擬時饼灿,可能會出現(xiàn)
Starting emulator for AVD 'EMU'
emulator: ERROR: x86 emulation currently requires hardware acceleration!
Please ensure Intel HAXM is properly installed and usable.
CPU acceleration status: HAXM is not installed on this machine
此時可以在sdk manager下載extra中的HAXM或者h(yuǎn)ttps://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager-intel-haxm下載并安裝
異常:未安裝sdk
Traceback (most recent call last):
File "C:\Users\liujiey\Desktop\test.py", line 20, in setUp
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
File "build\bdist.win32\egg\appium\webdriver\webdriver.py", line 36, in __init__
super(WebDriver, self).__init__(command_executor, desired_capabilities, browser_profile, proxy, keep_alive)
File "C:\Python27\lib\site-packages\selenium-2.48.0-py2.7.egg\selenium\webdriver\remote\webdriver.py", line 87, in __init__
self.start_session(desired_capabilities, browser_profile)
File "C:\Python27\lib\site-packages\selenium-2.48.0-py2.7.egg\selenium\webdriver\remote\webdriver.py", line 141, in start_session
'desiredCapabilities': desired_capabilities,
File "C:\Python27\lib\site-packages\selenium-2.48.0-py2.7.egg\selenium\webdriver\remote\webdriver.py", line 201, in execute
self.error_handler.check_response(response)
File "C:\Python27\lib\site-packages\selenium-2.48.0-py2.7.egg\selenium\webdriver\remote\errorhandler.py", line 181, in check_response
raise exception_class(message, screen, stacktrace)
WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Could not find adb Please set the ANDROID_HOME environment variable with the Android SDK root directory path.
一個測試樣例
創(chuàng)建腳本
一個測試腳本樣例:
import os
import unittest
from appium import webdriver
from time import sleep
# Returns abs path relative to this file and not cwd
class ContactsAndroidTests(unittest.TestCase):
def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '4.2'
desired_caps['deviceName'] = 'Android Emulator'
//desired_caps['app'] = 'E://ContactManager.apk'
desired_caps['appPackage'] = 'com.example.android.contactmanager'
desired_caps['appActivity'] = '.ContactManager'
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
def tearDown(self):
self.driver.quit()
def test_add_contacts(self):
el = self.driver.find_element_by_accessibility_id("Add Contact")
el.click()
textfields = self.driver.find_elements_by_class_name("android.widget.EditText")
textfields[0].send_keys("Appium User")
textfields[2].send_keys("someone@appium.io")
self.assertEqual('Appium User', textfields[0].text)
self.assertEqual('someone@appium.io', textfields[2].text)
self.driver.find_element_by_accessibility_id("Save").click()
# for some reason "save" breaks things
alert = self.driver.switch_to_alert()
# no way to handle alerts in Android
self.driver.find_element_by_android_uiautomator('new UiSelector().clickable(true)').click()
self.driver.press_keycode(3)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(ContactsAndroidTests)
unittest.TextTestRunner(verbosity=2).run(suite)
Desired Capabilities
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '4.2'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['app'] = '../../../sample-code/apps/ContactManager/ContactManager.apk'
desired_caps['appPackage'] = 'com.example.android.contactmanager'
desired_caps['appActivity'] = '.ContactManager'
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
-
deviceName:啟動哪種設(shè)備幕侠,是真機還是模擬器?iPhone Simulator碍彭,iPad Simulator晤硕,iPhoneRetina 4-inch悼潭,Android Emulator,Galaxy S4…
deviceName通過adb devices查看
platformName:使用哪種移動平臺窗骑。iOS, Android, orFirefoxOS女责。
platformVersion:指定平臺的系統(tǒng)版本漆枚。例如指的Android平臺创译,版本為5.1。
app:apk文件的路徑墙基,appium會嘗試先安裝該app软族。
appActivity:待測試的app的Activity名字。比如MainActivity残制、.Settings立砸。注意,原生app的話要在activity前加個”.“初茶。
appPackage:待測試的app的Java package颗祝。比如com.example.android.myApp, com.android.settings。
appActivity和appPackage一般由開發(fā)人員提供恼布,如果無法獲取的話螺戳,可以通過以下方式獲取
1、用winrar打開apk
2折汞、選擇AndroidManifest.xml倔幼,右鍵查看文件
3、查看
其中:m a n i f e s t " c o m . e x a m p l e . a n d r o i d . c o n t a c t m a n a g e r"就是appPackage
其中:a c t i v i t y ? . C o n t a c t M a n a g e r 就是appActivity
v e r s i o n C o d e
v e r s i o n N a m e
m i n S d k V e r s i o n ? t a r g e t S d k V e r s i o n ? n a m e ? l a b e l ? i c o n
d e b u g g a b l e ? a n d r o i d * h t t p : / / s c h e m a s . a n d r o i d . c o m / a p k / r e s / a n d r o i d ? p a c k a g e m a n i f e s t " c o m . e x a m p l e . a n d r o i d . c o n t a c t m a n a g e r ? 1 . 0 u s e s - s d k ? u s e s - p e r m i s s i o n ? a n d r o i d . p e r m i s s i o n . G E T _ A C C O U N T S a n d r o i d . p e r m i s s i o n . R E A D _ C O N T A C T S ! a n d r o i d . p e r m i s s i o n . W R I T E _ C O N T A C T S
a p p l i c a t i o n a c t i v i t y ? . C o n t a c t M a n a g e r
i n t e n t - f i l t e r ? a c t i o n ? a n d r o i d . i n t e n t . a c t i o n . M A I N c a t e g o r y a n d r o i d . i n t e n t . c a t e g o r y . L A U N C H E R
appium 定位控件
這里通過appium自帶的Inspector工具可以查看對象各種屬性爽待。也可以用android sdk自帶的uiautomatorviewer.bat來進(jìn)行定位
1损同、啟動appium server
2、啟動模擬器鸟款,并安裝待測試的apk:ContactManager.apk(將文件拖入模擬器即可)
3膏燃、模擬器中打開ContactManager.apk,放在待測試的頁面
4何什、點擊Start Inspector session圖標(biāo)
5组哩、在name和value處分別輸入以下內(nèi)容,點擊start session啟動
platformName Android
platformVersion 4.2
deviceName Android Emulator
appPackage com.example.android.contactmanager
appActivity ContactManager
界面如下
錄制腳本
Inspector提供了簡單的腳本操作
1富俄、選擇錄制腳本
2禁炒、在頁面上做一些操作,比如點擊等
3霍比、可以看到頁面上有腳本出現(xiàn)幕袱,復(fù)制腳本即可
定位元素信息
選中一個元素就可以實現(xiàn)定位,頁面右側(cè)展示了元素具體的內(nèi)容
注意:出現(xiàn)不能點擊鼠標(biāo)來進(jìn)行定位的話悠瞬,可以選用uiautomatorviewer.bat來進(jìn)行定位们豌,或者兩個結(jié)合使用涯捻。
id 定位
如果目標(biāo)設(shè)備的API Level低于18則UIAutomatorViewer不能獲得對應(yīng)的Resource ID,只有等于大于18的時候才能使用望迎。
resource-id 就是我們理解的id屬性了障癌。
使用方法:
driver.findElement(By.id("com.android.calculator2:id/formula"))
name 定位
text就是我們要查找的name!
使用方法:
driver.findElement(By.name("21"))
Accessibility ID定位
這個方法屬于Appium擴(kuò)展的定位方法辩尊。
其實涛浙,我們的核心是要找到元素的contentDescription屬性。它就是元素的 content-desc 摄欲。
使用方法:
driver.findElementByAccessibilityId("Add contact").click();
android uiautomator定位
這個方法也屬于 Appium(Android)擴(kuò)展的定位方法轿亮。
也就是說一個元素的任意屬性都可以通過android uiautomator方法來進(jìn)行定位,但要保證這種定位方式的唯一性胸墙。
使用方法:
driver.find_element_by_android_uiautomator('new UiSelector().text("Custom View")').click() driver.find_element_by_android_uiautomator('new UiSelector().textContains("View")').click()
driver.findElementByAndroidUIAutomator('new UiSelector().description("equals")").click();
需要注意的是 description() 方法用的是content-desc屬性我注。
find_elements_by_class_name方法
方法:
- find_elements_by_class_name()
通過元素class name屬性定位所有含有該屬性的元素
driver.find_elements_by_class_name('name')
appium API
sendKeys()方法
方法:
- sendKeys()
用法:
driver.findElements(By.name("Name")).sendKeys("jack");
pressKeyCode()方法
除此之外,appium擴(kuò)展提供了pressKeyCode()方法迟隅。該方法Android特有但骨。
方法:
- pressKeyCode()
發(fā)送一個鍵碼的操作。需要一個入?yún)ⅰ?/p>
driver.pressKeyCode(29); // 字母“a”
driver.pressKeyCode(3);//KEYCODE_HOME
switch_to_alert()方法
方法:
- switch_to_alert()
切換到alert窗口
driver.switch_to_alert()
click()方法
方法:
- click()
點擊某個控件
element.click()
API文檔參考:http://blog.csdn.net/yangyinsong815/article/details/51235708
至此智袭,腳本中所有的知識點講解完畢奔缠,現(xiàn)在開始運行它吧!運行之前請確保模擬器打開补履!
真機運行
模擬器并不能模擬真實的手機執(zhí)行添坊,最終我們的案例還是需要在真機中進(jìn)行。
真機和模擬器執(zhí)行的區(qū)別在于:
真機運行需要打開USB調(diào)試所有項