目錄
- 任務(wù)目標(biāo)
- 安卓App構(gòu)建滥玷、打包、部署與自動(dòng)化測(cè)試
- 安卓App持續(xù)集成體系建設(shè)實(shí)戰(zhàn)
一巍棱、任務(wù)目標(biāo)
- 實(shí)戰(zhàn)任務(wù)的故事
- 從源碼制作出可運(yùn)行App惑畴,支持測(cè)試工作
- 各種自動(dòng)任務(wù)
- Daily Build打包
- Daily Build發(fā)布
- Daily Build UI自動(dòng)測(cè)試(BVT - Build Verification Test)
- 利用技術(shù)來(lái)幫助做 “雜活兒”
- 優(yōu)勢(shì):
- 重復(fù)性定式勞動(dòng)任務(wù),
- 減少人力參與航徙,提升工作效率
- Build不再是阻礙測(cè)試進(jìn)度的因素
- 自動(dòng)化重用率高如贷,維護(hù)頻率低
二、 安卓App構(gòu)建到踏、打包杠袱、部署與自動(dòng)化測(cè)試
涉及技術(shù)點(diǎn)
- Android App構(gòu)建
- Android SDK使用
- 安卓模擬器或真機(jī)
- Python + Appium自動(dòng)化測(cè)試
- Jenkins持續(xù)集成
- Shell腳本開(kāi)發(fā)
- Java程序開(kāi)發(fā)
- Git ( github使用)
測(cè)試App構(gòu)建、打包過(guò)程
- Android應(yīng)用(例子程序)
- 源碼位置:https://github.com/princeqjzh/AndroidSampleApp
- 安卓打包的目標(biāo)文件:app-debug.apk文件
- 安卓打包命令:
gradlew clean assembleDebug
- 安卓安裝包的輸出路徑:
/app/build/outputs/apk/debug/app-debug.apk
- 關(guān)于安卓打包的環(huán)境要求
- JDK 1.8
- Android SDK
-
Gradle
安卓App部署
-
前提條件:
- 安卓實(shí)體機(jī)或者安卓模擬器
- 安卓SDK
目標(biāo):通過(guò)命令安裝/卸載App
-
命令控制apk安裝與卸載
- 安裝:
adb install <file_ path>
- 卸載:
adb uninstall <package_ name>
- 安裝:
-
查找包名:
adb shell pm list packages | grep sample
安卓UI自動(dòng)化測(cè)試
- Appium app自動(dòng)測(cè)試
- 源碼位置:https://github.com/princeqjzh/iAppBVT_Python
- 開(kāi)發(fā)工具:PyCharm
- UI自動(dòng)化框架:Appium
- 測(cè)試執(zhí)行框架:pytest
- 實(shí)現(xiàn)驗(yàn)證點(diǎn):
- App可安裝
- App可啟動(dòng)
- App首頁(yè)預(yù)期的元素存在
- 校驗(yàn)步驟
- 啟動(dòng)App
- 檢查Record Event是否存在
-
結(jié)束輸出結(jié)果
測(cè)試源碼
-
目錄樹(shù)
Readme.me
**iApp BVT自動(dòng)化測(cè)試程序(Python版)**
運(yùn)行環(huán)境:
- appium server
- python3
- unittest, pytest
- git
配置文件:iAppBVT_Python.json
- 將配置文件復(fù)制到本地磁盤(pán)
- 填入設(shè)備的 deviceName 與 udid
運(yùn)行命令:
pytest -sv test/bvt_test.py --tc-file /full path/iAppBVT_Python.json --tc-format json
- bvt_test.py 文件
from appium import webdriver
import unittest
import time
from pytest_testconfig import config
timeout = 30 # 超時(shí)
poll = 2 # 輪詢
class IAppBVT(unittest.TestCase):
def setUp(self):
desired_caps = {}
appium_server_url = config['appium_server_url']
desired_caps['platformName'] = config['desired_caps']['platformName']
desired_caps['udid'] = config['desired_caps']['udid']
desired_caps['deviceName'] = config['desired_caps']['deviceName']
desired_caps['appPackage'] = config['desired_caps']['appPackage']
desired_caps['appActivity'] = config['desired_caps']['appActivity']
desired_caps['automationName'] = config['desired_caps']['automationName']
desired_caps['noReset'] = config['desired_caps']['noReset']
self.driver = webdriver.Remote(appium_server_url, desired_caps)
def tearDown(self):
self.driver.quit()
def test_bvt(self):
print('BVT test is started!')
status = self.is_record_event_btn_exist()
print(f'The record event button is exist - {status}')
self.assertTrue(status, f'Check record_button result is {status}')
print('Test finished!')
def is_record_event_btn_exist(self):
elem = self._find_elem_by_xpath('//android.widget.Button[contains(@resource-id,"id/trackEventButton")]')
return elem is not None
def _find_elem_by_xpath(self, elem_xpath, time_out=timeout, raise_exception=True):
start = time.time()
elem = None
while time.time() - start < time_out and elem is None:
time.sleep(poll)
try:
elem = self.driver.find_element_by_xpath(elem_xpath)
except Exception:
print('by pass the element not found')
if elem is None and raise_exception:
raise LookupError(f'The element which xpath is {elem_xpath} could not be found')
return elem
- iAppBVT_Pyhon.json 文件
- 獲取udid:
adb devices
{
"desired_caps": {
"platformName": "Android",
"deviceName": "<your device name>",
"udid": "<your device udid>",
"noReset": "false",
"automationName": "UiAutomator2",
"appPackage": "com.appsflyer.androidsampleapp",
"appActivity": ".MainActivity"
},
"appium_server_url": "http://localhost:4723/wd/hub"
}
- requirements.txt
allure-pytest
appium-python-client
pytest
pytest-testconfig
requests
selenium
urllib3
三窝稿、安卓App持續(xù)集成體系建設(shè)實(shí)戰(zhàn)演練
- 將之前內(nèi)容所做事情用Jenkins任務(wù)來(lái)實(shí)現(xiàn)
- Jenkins平臺(tái)源碼構(gòu)建楣富、打包、發(fā)布app測(cè)試包
- Jenkins自動(dòng)部署伴榔、測(cè)試新app測(cè)試包
- Jenkins通知運(yùn)行結(jié)果
實(shí)現(xiàn)流程圖
安卓打包任務(wù)
安卓APP發(fā)布 輸出apk文件
安卓app自動(dòng)部署纹蝴、測(cè)試任務(wù)
App打包任務(wù)與自動(dòng)部署、測(cè)試任務(wù)關(guān)聯(lián)
-
實(shí)現(xiàn)完成打包任務(wù)之后踪少,運(yùn)行自動(dòng)測(cè)試任務(wù)塘安,安裝新包,并運(yùn)行UI自動(dòng)測(cè)試驗(yàn)證新安裝包的正確性
配置任務(wù)結(jié)果郵件通知
- 任務(wù)完成之后要把結(jié)果周知到相關(guān)人員秉馏,可以通過(guò)email的方式進(jìn)行通知
-
結(jié)果通知:任務(wù)正確完成
三耙旦、安卓App持續(xù)集成體系建設(shè)實(shí)戰(zhàn)
創(chuàng)建打包任務(wù)
-
創(chuàng)建job
-
選擇任務(wù)運(yùn)行的節(jié)點(diǎn)-master
-
添加項(xiàng)目的GitHub地址,并復(fù)制項(xiàng)目名稱
-
將復(fù)制的項(xiàng)目名稱復(fù)制到sub-directory
添加shell命令
. ~/.bash_profile
cd AndroidSampleApp
sh gradlew clean assembleDebug
-
添加發(fā)布路徑:
AndroidSampleApp/app/build/outputs/apk/debug/app-debug.apk
-
進(jìn)行構(gòu)建萝究,查看控制臺(tái)輸出以及運(yùn)行結(jié)果
創(chuàng)建自動(dòng)化測(cè)試任務(wù)
-
創(chuàng)建任務(wù)
-
選擇打包的機(jī)器
-
添加項(xiàng)目的GitHub地址免都,復(fù)制項(xiàng)目名稱
-
粘貼項(xiàng)目名稱到sub-directory
輸入shell命令
- 如果apk 不存在執(zhí)行
uninstall
命令會(huì)報(bào)錯(cuò),可以用以下命令過(guò)渡帆竹,中間的| |
是或者的意思绕娘,先之前前面的命令,如果前面的命令報(bào)錯(cuò)則執(zhí)行后面的命令
{
adb uninstall com.appsflyer.androidsampleapp
} | | {
echo 'no app package installed on the device'
}
-
pwd
命令是為了獲取當(dāng)前路徑
. ~/.bash_profilepwd= `pwd`
apk=$pwd/../1219_buildAndroidsample/AndroidSampleApp/app/build/outputs/apk/debug/app-debug.apk
{
adb uninstall com.appsflyer.androidsampleapp
}||{
echo 'no app package installed on the device'
}
adb install $apk
cd iAppBVT_Python
pip3.9 install -r requirements.txt
pytest -sv test/bvt_test.py --tc-file /Users/jizhiqian/iAppBvT_Python.json --tc-format json
-
構(gòu)建job栽连,進(jìn)行運(yùn)行
配置消息通知
-
打包job和自動(dòng)化測(cè)試job添加 Email Notification
關(guān)聯(lián)任務(wù)
-
在打包job中添加關(guān)聯(lián)险领,Post-bulid Actions -> Build other projects
構(gòu)建打包任務(wù)會(huì)自動(dòng)觸發(fā)自動(dòng)化測(cè)試腳本
四、課程總結(jié)
- 從源碼到可測(cè)包秒紧,外加自動(dòng)化測(cè)試驗(yàn)證的全流程持續(xù)集成體系建設(shè)
- 安卓App的構(gòu)建绢陌、打包方法
- Apk文件發(fā)布
- 觸發(fā)自動(dòng)測(cè)試
- Appium UI自動(dòng)化測(cè)試
- 利用Jenkins平臺(tái)進(jìn)行持續(xù)集成演練
五、FAQ
如何做失敗后的自動(dòng)重試
- 在job的 Post-build Actions 中添加 Retry build after failure 插件
- Fixed -> Fixed delay:表示延遲多少秒再次構(gòu)建
- Maximum number of successive failed builds:重試次數(shù)
- 可以捕捉錯(cuò)誤信息熔恢,使用正則表達(dá)式脐湾,
|
表示或