Jenkins持續(xù)集成體系建設(shè)

目錄

  • 任務(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


      image.png

      image.png
安卓App部署
  • 前提條件:

    • 安卓實(shí)體機(jī)或者安卓模擬器
    • 安卓SDK
  • 目標(biāo):通過(guò)命令安裝/卸載App

  • 命令控制apk安裝與卸載

    • 安裝:adb install <file_ path>
    • 卸載:adb uninstall <package_ name>
  • 查找包名:adb shell pm list packages | grep sample

    image.png

安卓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é)果


      image.png

測(cè)試源碼

  • 目錄樹(shù)


    image.png
  • 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
    image.png
{
    "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)流程圖

image.png

安卓打包任務(wù)

image.png

安卓APP發(fā)布 輸出apk文件

image.png

安卓app自動(dòng)部署纹蝴、測(cè)試任務(wù)

image.png

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)證新安裝包的正確性


    image.png

配置任務(wù)結(jié)果郵件通知

  • 任務(wù)完成之后要把結(jié)果周知到相關(guān)人員秉馏,可以通過(guò)email的方式進(jìn)行通知
image.png
  • 結(jié)果通知:任務(wù)正確完成


    image.png

三耙旦、安卓App持續(xù)集成體系建設(shè)實(shí)戰(zhàn)

創(chuàng)建打包任務(wù)

  1. 創(chuàng)建job


    image.png
  2. 選擇任務(wù)運(yùn)行的節(jié)點(diǎn)-master


    image.png
  3. 添加項(xiàng)目的GitHub地址,并復(fù)制項(xiàng)目名稱


    image.png
  4. 將復(fù)制的項(xiàng)目名稱復(fù)制到sub-directory


    image.png
  5. 添加shell命令

. ~/.bash_profile
cd AndroidSampleApp
sh gradlew clean assembleDebug
image.png
  1. 添加發(fā)布路徑:AndroidSampleApp/app/build/outputs/apk/debug/app-debug.apk

    image.png

  2. 進(jìn)行構(gòu)建萝究,查看控制臺(tái)輸出以及運(yùn)行結(jié)果


    image.png

    image.png

創(chuàng)建自動(dòng)化測(cè)試任務(wù)

  1. 創(chuàng)建任務(wù)


    image.png
  2. 選擇打包的機(jī)器


    image.png
  3. 添加項(xiàng)目的GitHub地址免都,復(fù)制項(xiàng)目名稱


    image.png
  4. 粘貼項(xiàng)目名稱到sub-directory


    image.png
  5. 輸入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
image.png
  1. 構(gòu)建job栽连,進(jìn)行運(yùn)行


    image.png

配置消息通知

  • 打包job和自動(dòng)化測(cè)試job添加 Email Notification


    image.png

關(guān)聯(lián)任務(wù)

  • 在打包job中添加關(guān)聯(lián)险领,Post-bulid Actions -> Build other projects


    image.png

構(gòu)建打包任務(wù)會(huì)自動(dòng)觸發(fā)自動(dòng)化測(cè)試腳本

image.png

image.png

四、課程總結(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á)式脐湾,| 表示或
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市叙淌,隨后出現(xiàn)的幾起案子秤掌,更是在濱河造成了極大的恐慌愁铺,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闻鉴,死亡現(xiàn)場(chǎng)離奇詭異茵乱,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)孟岛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)瓶竭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蚀苛,你說(shuō)我怎么就攤上這事在验。” “怎么了堵未?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)盏触。 經(jīng)常有香客問(wèn)我渗蟹,道長(zhǎng),這世上最難降的妖魔是什么赞辩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任雌芽,我火速辦了婚禮,結(jié)果婚禮上辨嗽,老公的妹妹穿的比我還像新娘世落。我一直安慰自己,他們只是感情好糟需,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布屉佳。 她就那樣靜靜地躺著,像睡著了一般洲押。 火紅的嫁衣襯著肌膚如雪武花。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天杈帐,我揣著相機(jī)與錄音体箕,去河邊找鬼。 笑死挑童,一個(gè)胖子當(dāng)著我的面吹牛累铅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播站叼,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼娃兽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了大年?” 一聲冷哼從身側(cè)響起换薄,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤玉雾,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后轻要,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體复旬,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年冲泥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了驹碍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凡恍,死狀恐怖志秃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嚼酝,我是刑警寧澤浮还,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站闽巩,受9級(jí)特大地震影響钧舌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜涎跨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一洼冻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隅很,春花似錦撞牢、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至审编,卻和暖如春撼班,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背垒酬。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工砰嘁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人勘究。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓矮湘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親口糕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缅阳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容