Appium iOS 測試指令碼開發實戰
最近老闆家心情好,不停的給UI加了好多的任務,iOS開發部門的小哥哥見到UI妹妹的眼神由愛轉嫌棄,飽含深深地怨氣,每個周都會釋出一個迭代;迴歸測試就是一個繁瑣又不能忽略的事,沒辦法就是懶,不想繼續點點點,乾脆寫個弱弱的iOS測試指令碼,滿足下自己懶得慾望,一番調研,選擇了Appium作為iOS的測試框架,當然我沒找到更合適的框架了;一週小成,分享出來,開心開心,大佬屠刀輕點,同為菜鳥慢慢吐槽?
首先,開發iOS測試指令碼的最重要前提是你的有一臺macOS系統的裝置
安裝jdk,弱弱的問一句,哪位和開發沾點邊的電腦沒有jdk;Java -version檢查下吧
接下來就是安裝node.js,有好多寫的很好的博文,不懂的可以移步瞭解下,檢查下您家電腦的node是否安裝成功吧
附帶的,檢查下您家電腦的npm是否可以正常使用吧
安裝完成了以上的幾個小東西,接下來就是安裝我們尊貴的Appium了,Appium有兩種,一種是桌面版,一種是命令列模式,這裡建議安裝桌面版的Appium-desktop,附上下載連結,下載後裝即可;
https://github.com/appium/appium-desktop/releases
安裝完成即可啟動
僅僅是安裝完成Appium-desktop可不代表可以您能開始的秀上您的優雅程式碼,我這這個坑硬是填了整整一天,Appium-desktop始終無法和客戶端進行通訊,一直髮生各種各樣的報錯,抑鬱症狂犯;
到這裡,先需要檢查下Appium是否安裝了它所需要的類庫,最好的方式就是使用其自帶的appium-doctor檢查下。
在命令列客戶端中輸入appium-doctor,appium-doctor就會自動檢查類庫的安裝是否完整,當沒安裝完整是就會在圖中的紅框部分顯示出來,這時你需要根據提示將缺失的類庫一一安裝,直到不再爆紅(以上爆紅為安卓測試需要用到的adb和sdk,這裡測試iOS,不進行處理)
到這裡,Appium-desktop的安裝完成,看看他的盛世美顏吧
要想和手機進行通訊,最重要的一環是安裝WebDeiverAgent,安裝WebDeiverAgent可能需要iOS開發同事的幫忙,但是你如果很瞭解xcode的使用情況下,可以自行下載,並完成編譯,這部分的安裝我暫且不做介紹,因為我之前也是根據大神的教程來完成安裝的,需要的可以參考大神們的作品;編譯完成後模擬器上會WebDriverAgent的圖示,點選圖示會啟動然後結束,很像閃退的效果
之前推薦大家安裝desktop版本的原因就是desktop版本可以擷取到App UI的結構,配置好即可啟動,並讀取App的UI結構,點選紅框部分進入到UI框架讀取介面
配置好需要的desired capabilities,點選啟動即可,其中每一項的內容分析會在下一部分一一解析
{
"bundleId": "com.latsen.Pawfit",
"deviceName": "Simulator",
"platformVersion": "14.2",
"platformName": "iOS",
"automationName": "Appium",
"noReset": true,
"udid": "F1B7F19F-C517-4587-8DE5-8EE73B8BBFDF"
}
啟動看看結果吧
好的,第一個階段算是完成了,環境搭建是我覺得這一個開發iOS測試指令碼的最難部分,安裝期間會遇到各種各樣的問題,可以百度仰慕下大神的作品及其解決方案,祝您順利
這個準備也是需要費點時間的工作,我這裡三言兩語就說完,但不代表這個步驟很簡單,出現的意外可能就會讓您前面的努力白費;
準備好您的模擬器或者手機,這裡建議使用模擬器測試,手機會因為SDK的問題導致無法連線到手機,啟動模擬器;
接下來就是準備好需要測試的APP檔案,這個地方需要注意下,如果該APP檔案不適配您的電腦,
啟動APP請求網路是時APP會閃退,從而無法進行開發,我自然就遇到過,奇怪的就是網上為何都沒出現過呢???為此,我花了三瓶可樂來招待開發小哥哥?;檢查下APP是否可以正常在中執行
文件準備,官方的穩定簡直就是爛透了,這裡建議使用看雲的文件,可能需要登入
https://www.kancloud.cn/testerhome/appium_docs_cn/2001597
Appium配置文件
https://appium.io/docs/cn/writing-running-appium/caps/
完成了以上的折磨後,現在可以開啟美麗的開發過程了,啟動你的編譯器吧
pip安裝appium的python客戶端程式碼
pip install Appium-Python-Client
from appium import webdriver
my_ios_driver=None
import json
class my_driver(object):
session=None
def __init__(self):
self.session=self.get_my_driver(self.get_deried_cap())
def get_deried_cap(self):
caps = {}
#APP檔案在電腦中的位置,當模擬器中安裝後,可以去掉該配置
# caps["app"] = "/Users/kefeng/Desktop/Pawfit1230_1.zip"
#將測試APP的包名
caps["bundleId"] = "com.latsen.Pawfit"
#模擬器名稱
caps["deviceName"] = "Simulator"
#模擬器系統版本
caps["platformVersion"] = "14.2"
#測試的平臺
caps["platformName"] = "iOS"
#測試期間使用的驅動
caps["automationName"] = "XCUITest"
#是否需要重置APP,不需要寫False
caps["noReset"] = True
#命令執行的超時時間,這個很重要
caps["newCommandTimeout"]=600
#是否中斷回話,並重啟app
caps['autoLaunch']=False
#裝置的UDID
caps["udid"] = "F1B7F19F-C517-4587-8DE5-8EE73B8BBFDF"
return caps
def get_my_driver(self,caps):
driver=webdriver.Remote("http://localhost:4723/wd/hub", caps)
driver.set_page_load_timeout(50000)
driver.set_script_timeout(50000)
driver.implicitly_wait(10)
# 設定許可權,可根據xcrun simctl privacy命令檢視
return driver
def disconnect(self):
my_ios_driver.quit()
my_ios_driver=my_driver().session
if __name__ == '__main__':
my_ios_driver.execute_script('mobile: setPermission','io.appium.example',{ 'location-always': 'yes'})
以上註釋中提到的幾個配置項都非常非常重要,如果配置錯誤,將無法啟動;
#是否中斷回話,並重啟app caps["newCommandTimeout"]=600 #是否中斷回話,並重啟app caps['autoLaunch']=False
這兩項在測試和開發中相當重要,尤其是caps['autoLaunch']=False,他可以幫助你不用每次重啟APP即可進行測試,這在開發中極其的方便,我們並不是每次都想重啟APP來進行測試,尤其是後期再testsuit套件測試時;
開發過程中,經常會出現的錯誤就是元素查詢異常,Appium提供了多樣的元素獲取方式,如下:
根據類名:
#根據類名:
pet_breed=my_ios_driver.find_element_by_class_name('XCUIElementTypeTextField')[
pet_breed=my_ios_driver.find_elements_by_class_name('XCUIElementTypeTextField')[2]
#根據xpath
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Dog"]').click()
my_ios_driver.find_elements_by_xpath('//XCUIElementTypeButton[@name="Dog"]')[0].click()
#根據predicate
my_ios_driver.find_element_by_ios_predicate('label == "Female"').click()
當然還會有其他的,可以根據您的需求來選擇,例如我常用的程式碼截選
當然還會有其他的,可以根據您的需求來選擇,例如我常用的程式碼截選
if type == "SUBSCRIBABLE" and status == "INACTIVE":
# paypal方式使用手動測試
pay_method = "1"
if str(pay_method) == '1':
device_id.clear()
device_id.send_keys(barcode)
self.hide_key_board()
bind_buttom.click()
sleep(5)
# 啟動支付流程
# 檢查優惠碼有效性
code=my_ios_driver.find_element_by_class_name('XCUIElementTypeTextField')
# 檢查無效
code.clear()
code.send_keys("@@@@@@@")
self.hide_key_board()
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Buy now"]').click()
sleep(5)
# 檢查過期優惠碼
code.clear()
code.send_keys("asdfgv")
self.hide_key_board()
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Buy now"]').click()
sleep(5)
# 已經被使用
code.clear()
code.send_keys("qawsde")
self.hide_key_board()
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Buy now"]').click()
# TODO 優惠碼支付,請完善
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="OK"]').click()
#返回繫結介面,等待繫結完成
sleep(10)
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="OK"]').click()
else:
#TODO 由於paypal的原因,支付完成後可能會出現pending狀態而無法繼續接著其他步驟,可能需要單獨處理
device_id.clear()
device_id.send_keys(barcode)
self.hide_key_board()
bind_buttom.click()
sleep(5)
buy_now=my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Buy now"]')
buy_now.click()
sleep(5)
my_ios_driver.find_elements_by_class_name('XCUIElementTypeButton')[2].click()
sleep(5)
if self.utis.exists('xpath','//XCUIElementTypeButton[@name="Next"]',30):
my_ios_driver.find_element_by_class_name('XCUIElementTypeTextField').send_keys("accounting-buyer@latsen.com")
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Next"]').click()
sleep(10)
my_ios_driver.find_element_by_class_name('XCUIElementTypeSecureTextField').send_keys("paypalDev123")
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Log in"]').click()
else:
my_ios_driver.find_element_by_class_name('XCUIElementTypeTextField').send_keys("accounting-buyer@latsen.com")
my_ios_driver.find_element_by_class_name('XCUIElementTypeSecureTextField').send_keys("paypalDev123")
self.hide_key_board()
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Log in"]').click()
sleep(15)
my_ios_driver.execute_script("mobile:swipe", {"direction": "up", 'element': my_ios_driver.find_element_by_xpath(' //XCUIElementTypeStaticText[@name="Pay with"]'), "duration": 1})
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Agree and Subscribe"]').click()
else:
device_id.clear()
device_id.send_keys(barcode)
self.hide_key_board()
bind_buttom.click()
# 優惠碼購買完成,但伺服器裝置狀態未進行更改
#處理不同型號機器彈框不同問題
# sleep(10)
# my_ios_driver.set_page_load_timeout(10000)
sleep(15)
if type=="SUBSCRIBABLE":
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="OK"]').click()
#P
else:
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Yes"]').click()
用到sleep簡直就是噩夢,但不得不用,官方的等待方式經常會導致元素查詢異常,哪怕我已經做了異常處理,場景多變,況且我還是菜;
# TODO 修改程式碼,返回一個元組,裡面裡面存放元素是否存在和控制元件物件
# TODO 修改程式碼,返回一個元組,裡面裡面存放元素是否存在和控制元件物件
def exists(self, what_method, resource_text, timeout=1):
i = 0
flag = False
driver = my_ios_driver
while timeout > i:
try:
if what_method == "accid":
driver.find_element_by_accessibility_id(resource_text)
elif what_method == "class":
driver.find_element_by_class_name(resource_text)
elif what_method == "css":
driver.find_element_by_class_name(resource_text)
elif what_method == "xpath":
driver.find_element_by_xpath(resource_text)
elif what_method == "pred":
driver.find_element_by_ios_predicate(resource_text)
elif what_method == "tag":
driver.find_element_by_tag_name(resource_text)
elif what_method == "name":
driver.find_element_by_name(resource_text)
elif what_method == "id":
driver.find_element_by_id(resource_text)
flag = True
return flag
except Exception as e:
print(e)
i += 1
continue
return flag
更多的程式碼細節不能太多暴露,請原諒
配合unittest使用,設計合理的測試流程,即可完成整個APP的全部用例的測試;
from ios.ios_app_edit_user_info_testcase import test_edit_user_profile
from ios.ios_app_register_testcase import Register_TestCase
from ios.ios_app_edit_pet_info_testcase import Edit_Pet_Info
if __name__ == '__main__':
testcase = unittest.TestLoader().loadTestsFromTestCase(Login_Test)
test_edit_user_profile = unittest.TestLoader().loadTestsFromTestCase(test_edit_user_profile)
FindPassword = unittest.TestLoader().loadTestsFromTestCase(FindPassword)
Register_TestCase = unittest.TestLoader().loadTestsFromTestCase(Register_TestCase)
add_pet=unittest.TestLoader().loadTestsFromTestCase(AddPet_TestCase)
edit_pet=unittest.TestLoader().loadTestsFromTestCase(Edit_Pet_Info)
suite = unittest.TestSuite([testcase,add_pet,edit_pet,test_edit_user_profile,FindPassword,Register_TestCase])
report='/Users/kefeng/Documents/TestCases/reports/testcase_report.html'
with(open(report, 'wb')) as fp:
runner = HTMLTestRunner(
stream=fp,
title='<project name> iOS 測試報告',
description='describe: iOS 測試報告'
)
runner.run(suite)
原先想著可以錄屏給親們看個效果,但是發現模擬器似乎沒有錄屏功能,如果下次拿到錄屏,一定給補上?
一下截圖是測試結束後的報告,全部59個testcase可以在17分鐘完成測試,下次可以喝著肥宅水,看著自動化指令碼執行即可,當然目前程式碼的健壯性需要加強,大家一起努力吧
目錄
祝願和我一樣的菜鳥能快速成長,開心每一天。
相關文章
- 測試開發之自動化篇-Appium指令碼開發APP指令碼
- iOS17 效能測試指令碼iOS指令碼
- QTP專案實戰課程測試指令碼下載QT指令碼
- JavaScript 實戰開發經驗!“智力”測試JavaScript
- node 執行JavaScript 指令碼 測試axiosJavaScript指令碼iOS
- 測試開發必備技能:安全測試漏洞靶場實戰
- 用Python開發自動化測試指令碼Python指令碼
- iOS 開發-單元測試iOS
- 測試驅動開發(TDD)實戰心得 - DeniMoka
- LoadRunner JAVA Vuser協議開發效能測試指令碼Java協議指令碼
- mysql鎖 實戰測試程式碼MySql
- Appium+Python實現iOS自動化測試~環境搭建APPPythoniOS
- iOS appium UI 自動化測試配置可控 xpathiOSAPPUI
- appium ios java 指令碼如何用指令執行,例如 adb 那種方式執行指令碼APPiOSJava指令碼
- 基於Python的測試驅動開發實戰Python
- PYTHON測試指令碼Python指令碼
- 壓力測試指令碼指令碼
- [Mysql]效能測試指令碼MySql指令碼
- Appium自動化測試之微信h5元素識別和程式碼實戰APPH5
- 開源測試工具 JMeter 介紹 - 物聯網大併發測試實戰 01JMeter
- shell指令碼和python指令碼實現批量ping IP測試指令碼Python
- appium 安卓應用指令碼APP安卓指令碼
- 基於測試驅動的iOS開發iOS
- web自動化測試框架-02 快速開發用例文件指令碼Web框架指令碼
- Android自動測試化之道1:Appium開發環境配置AndroidAPP開發環境
- iOS專案開發實戰——CoreLocation地理編碼和反地理編碼iOS
- python效能測試指令碼Python指令碼
- iOS打測試包與分發測試iOS
- iOS專案開發實戰——使用程式碼實現頁面跳轉iOS
- iOS開發那些事--編寫OCUnit測試方法-邏輯測試方法iOS
- 測試開發實戰[提測平臺]17-Flask&Vue檔案上傳實現FlaskVue
- [JPT_05] 效能測試-指令碼開發(登入&隨機購買業務)指令碼隨機
- mac上搭建appium+IOS自動化測試環境(一)MacAPPiOS
- Jmeter效能測試實戰JMeter
- WEB安全測試實戰Web
- 別老拿 “開發測試比” 挑戰 QA
- [python] request 介面測試自動化指令碼轉化為 [locust] 效能測試指令碼Python指令碼
- React Native iOS混合開發實戰教程React NativeiOS