本文由團隊内大瑤同學撰寫。
引言
移動App具有更新頻繁的特性,這一點,從各大App在應用市場的版本釋出頻率可見一斑。高頻釋出意味着迅速疊代和傳遞,這對需求、開發、測試、運維的效率提出了更高的要求。那麼,在快速變化的網際網路環境下,如何在保證品質的前提下,提高App的傳遞速度?這是業界共同面臨的問題。DevOps提供了解決該問題的答案,它倡導盡可能多地對軟體建構過程中的所有步驟進行自動化處理,也就是建構自動化流水線,以提高效率、縮短開發周期。在當今的IT領域,DevOps倡導的持續傳遞理念已經被普遍接受,實施DevOps實踐已經成為軟體組織管理的趨勢。近幾年,随着靈活軟體模式的深化,我們也一直在嘗試靈活、持續內建等實踐,以積極的态度擁抱DevOps。
值得重視的是,DevOps并非一個固定的模式或标準,事實上,業界對DevOps沒有統一的定義(而且DevOps的定義是随着時間不斷演變的)。它是一種普适的軟體工程文化和實踐,但每個企業的組織文化有差異,DevOps基礎也不盡相同,現有的一些成功方案往往并不完全适合團隊的實際情況,業界也不存在一個萬能的執行個體供我們複制。是以,應當基于自身實際情況,參考同類優秀案例和經驗,摸索出最适合自己的模式。一方面,我們缺乏專門的工具部門或團隊,短時間内無法建立起大型的一體化持續傳遞平台;另一方面,我們又急需建立起持續傳遞流水線,以改進靈活産品的開發測試流程。是以,我們以開源持續內建工具為核心,再适當開發輔助工具,建構了一個較為實用的App産品持續傳遞流水線。
随着App的功能日益複雜,與第三方合作的子產品越來越多,開發、測試階段聯調的難度也随之增加。同時,為迅速響應市場需求變化,App的疊代越來越快,釋出周期越來越短。工期緊、任務多,這給開發、測試人員帶來了很大的壓力,例如,開發為了按時完成代碼,擠壓了一些本來用于代碼評審、單元測試的時間,導緻項目代碼的品質下降;随之而來的是生産風險的提高,産品品質難以保障;開發需要花費額外的精力償還技術債(漏洞、不規範的代碼等),這又給新一輪疊代帶來風險——如此便陷入“疲于奔命”的惡性循環。
為解決上述問題,在參考DevOps等主流解決方案基礎上,我們也吸收DevOps和靈活理念,開展App産品持續傳遞流水線實踐,從工藝改進、組織文化等方面,改進App産品的持續傳遞實施過程,最終建構起一條完備的流水線。
與其他産品不同,App的傳遞比較特殊。例如,H5産品需要将部署包放置到伺服器上,并進行相應的配置,使用者就可以通過通路網址擷取服務;而安卓和IOS并不是部署在企業自己的伺服器上,而是需要在各自的應用市場“上架”,使用者才能從市場上擷取App,安裝到自己的手機上,完成傳遞過程。
對症方能下藥,我們首先必須明确,是什麼影響了App的疊代效率?經過分析和總結,我們發現,App的實施過程存在以下痛點:
1、開發任務繁重,代碼品質不高。
造成這一點的原因有很多,如需求規劃不合理、環境問題導緻聯調失敗、代碼評審不到位、測試覆寫不全面等。
2、版本分發效率低。
由于App産品的特殊性,使用者必須在手機上安裝新版本才能擷取其服務。在開發人員頻繁打出新版本的場景下,測試者需要及時獲得最新的App版本。然而現實情況通常是開發在自己的電腦上建構(俗稱“打包”),再把建構出的App安裝包發給測試人員——這樣人工的建構分發效率低,也難以保證建構出的安裝包是“合格”(即通過了單元測試、代碼掃描等必要的檢查環節)的。
3、容易出現不同環境下版本不一緻問題。
在測試階段,測試人員通常對測試環境下的版本進行測試,而産品釋出時,使用的是測試版本對應的生産版本,必須做到這個兩個版本除了環境相關的參數配置不同外,其他代碼完全一緻。然而從測試通過到人工切換成生産環境參數并建構生産版本的這段時間,可能會存在開發人員改動代碼的風險,導緻一個未經測試的App版本被釋出。是以,需要尋求同時建構多個不同環境參數的App的方案。
4、測試分析不到位,同類品質問題重複出現。
我們的目的不僅僅是修複問題,而且要保證日後不再發生同樣的錯誤。事實上,一個産品的缺陷可以給其他産品帶來啟發,我們需要吸取他人的經驗和教訓,加強不同産品之間的交流。
以上幾個問題,其實都是缺乏規範的流程、人工介入過多等原因造成的。當人工操作影響到工作效率時,應當考慮借助工具來節省人力,提高效率。
從工藝改進群組織文化兩個方面入手,逐漸建構起持續傳遞的實施流程和與之比對的組織結構。
1、從工藝改進的角度,建構App持續傳遞流水線。
● 分别對DevOps的各個步驟進行優化和改進,并組合成一條基于Jenkins自動化持續傳遞流水線,覆寫從需求到傳遞的各個環節,從實施流程上規範App傳遞的各個環節,如優化需求拆分、強化代碼評審等步驟,提高代碼品質。
● 自主開發小型工具,如App持續傳遞工具、擋闆系統等,完善上述流水線,以提高開發、測試效率。
2、進行組織結構調整,開展開發測試融合實踐。
● 在開發測試融合思維的導向下,開發與測試團隊被規劃到同一部門,這消除了部門壁壘,使得靈活疊代中開發、測試成為一個整體,強化了二者的溝通和聯系。
● 強化品質監督環節,測試團隊發揮QA作用。測試團隊不再僅僅負責傳統的測試工作,而是統籌測試實施、品質管理、工藝改進三大闆塊。在這種模式下,測試團隊不僅僅負責傳統的測試實施任務,還要深入靈活團隊,擔任QA角色,監督自動化測試、持續內建等環節,從更高層次上把控産品品質。
● 開展DevOps相關的交流活動,如開放日、系列教育訓練等,在部門内部、部門之間進行推廣和交流,互相借鑒經驗,培養員工的持續傳遞理念和能力。
在各類資源有限的情況下,我們必然要借助現有工具來支援持續傳遞實施過程。作為最受歡迎的CI工具之一,Jenkins成為我們的首選平台。它以插件的形式支援各種功能(官方提供了豐富的插件庫,開發者也可以根據官方API開發定制化插件)。此外,Jira、Sonarqube等受業界認可的工具成為流水線的組成部分。
1、App持續傳遞流水線
正所謂“工欲善其事,必先利其器”,自動化流水線的搭建必然需要借助工具。業界對于持續傳遞流水線工具的選擇,可以大概分為兩類:一是使用通用的CI、CD工具,二是使用一體化DevOps平台。前者靈活通用、不需要太多成本,但缺少業務元素;後者提供一站式解決方案,但通用性不強。
既然短時間内不具備采購或自主開發一體化DevOps平台的條件,我們選擇前者來實作傳遞流水線。如圖1所示,将各個環節如同串珠子一樣串聯起來,組合成完整的流水線。

圖1 App傳遞流水線
1)需求/知識:需求決定了任務量,進而決定了開發、測試的工作量,也直接影響代碼的品質。是以,要從流水線源頭進行改進,避免因需求規劃不合理影響開發效率。
● 過去:存在需求堆積、粒度過粗、變化頻繁,把開發“逼瘋”的情況;過分依賴人工看闆,不容易統計疊代燃盡圖、故事活躍度等資料。
● 現在:合理規劃需求、減少任務粒度,減輕疊代工作量,為實作小步傳遞做準備;使用Jira電子看闆,友善存檔使用者故事、問題等,更好地把控靈活健康狀況。
2)源代碼:使用SVN或Git托管代碼。代碼庫也有鄙視鍊,在大多程式員看來,似乎Git才是更“進階”的工具。其實,無論是SVN還是Git,都具備相當完備的功能,選擇哪一種工具并不重要,關鍵的是如何規範使用。
● 過去:由于并行任務多,分支政策混亂,代碼整合起來很複雜,耗費人力。
● 現在:逐漸轉換成串行任務,采取主幹開發政策,減少産品并行開發的情況;強化代碼送出紀律,如要求開發必須經過本地建構成功、單元測試通過、規範檢查通過後方可送出,且注意及時拉取和送出代碼。加強對關鍵邏輯代碼的管控和審查,改進代碼評審方式。
● 過去:人工走查的方式,經常一拖再拖,積壓了大量代碼,導緻走查時耗費大量時間,效果也難以保證。
● 現在:利用相關工具(如Gerrit)實施代碼評審環節,取代原始的人工走查。這樣既可以及時發現問題,又能減少開發人員的工作量。
● 過去:CI紀律形同虛設,常有建構失敗無人處理的情況。
● 現在:強化CI紀律,每個靈活組配置紅綠儀表盤,實時檢視動向。若有建構失敗,立即進行修複,修複不成功全組不下班。
3)代碼拉取:即Jenkins從代碼庫拉取代碼、觸發後續流水線/Job建構。這通常是Jenkins Job執行的第一步。
4)自動化測試:主要分為自動化單元測試、自動化接口測試、自動化UI測試三部分。其中自動化單元測試作為Job的一個環節,随着Job建構而執行;而其他兩類自動化測試則借助專門的自動化工具(RobotFramework、Appium)實施,在Jenkins上進行相應配置,可定時觸發和建構自動化測試Job。
5)靜态代碼掃描:對于代碼的品質,不能僅僅局限于那些“可視的”bug。代碼中往往存在大量潛在的問題,如健壯性問題、浮點數比較大小等,不容易被發現,但就像定時炸彈一樣,是産品品質的隐患。是以,我們借助靜态代碼掃描工具進行代碼掃描。例如,Sonarqube工具為各開發語言提供了靜态代碼掃描支援,使用者也可以自定義自己的規則。對于掃描出的各類問題,要求開發盡快解決。此外,Sonarqube還可以讀取自動化單元測試報告,并将單元測試結果展示在其儀表盤上,友善相關人員随時了解代碼品質。
6)安全掃描:增加安全掃描環節,提高代碼安全性。以Checkmarx安全掃描工具為例,在流水線中引入Checkmarx插件,觸發安全掃描環節。同時,對于掃描報告中出現的問題,要求開發予以解決,将問題及時歸零。
7)App加強:對App進行加強處理,防止被反編譯。
● 過去:使用用戶端進行加強。
● 現在:為了将加強環節自動化、納入持續傳遞過程,使用shell腳本調用加強指令,取代手動加強。
8)建構:前面的環節都是為了這一步做準備。對App産品而言,最終建構的結構是生成安裝包(ipa或apk)。App開發涉及開發、測試、灰階、生産環境,如何保證其處理環境參數外,其他代碼完全一緻,是值得我們關注的問題。對此,我們借助Jenkins的Pipeline流水線,提出并行建構機制。
● 過去:開發一般在開發、測試環境下編寫代碼,通過測試後,手動修改代碼裡的環境配置,然後建構出對應的生産版本,用于後續投産。若這個過程中有人修改了功能性代碼,則建構出的生産包包含未經過測試的代碼,直接投産的風險可想而知。
● 現在:項目代碼設定多環境(開發、生産、測試等環境)配置,執行建構指令時可指定環境,進而建構出對應環境的App版本;使用Pipeline并行腳本,同時建構出多個環境參數的版本,這幾個版本除了環境配置不同,其他完全一緻。在選取生産版本時,強制選擇其中的生産版本,該生産版本和測試版本同時被建構出,不存在被修改代碼的可能,可以保證App功能測試版本和生産版本一緻性。
9)制品:制品即安裝包,也就是建構出的版本,将被推送至App持續傳遞工具進行統一管理。
2、流水線中的工具建設
Jenkins不是萬能的,它隻提供了一個純粹的流水線引擎,不包含業務屬性。也就是說,Jenkins上的流水線無法關聯軟體管理周期中的需求、項目、任務、産品等元素,它們隻能是一個無層次的平行Job的集合。是以,上述環節并不能滿足App建設的實際需要。為此我們自主研發了幾個工具:App持續傳遞工具、QA儀表盤、多協定擋闆系統、錯題本,以進一步提高傳遞效率。
● App持續傳遞工具:App産品版本管理的平台,提供開發、測試、傳遞功能。
1)可對接Jenkins平台,擷取Jenkins制品,并按照其對應的環境參數,分階段統一管理,解決Jenkins Job無序、缺乏制品管理的問題;
2)App可通過掃描二維碼進行下載下傳安裝,取代原有的手工分發模式,極大地提高測試效率。
3)提供灰階釋出功能,用于App的灰階測試。
● 多協定擋闆系統:提供模拟接口,用于環境不聯通導緻真實接口無法調用的場景。開發人員不再手動編寫假資料,而是像調用真實接口一樣調用擋闆模拟出的接口,解決環境不通引發的進度阻塞問題。
1)實際開發階段、測試前期中,往往會遇到接口不通的問題,影響開發進度,使用該擋闆可以Mock接口。
2)現有接口不具備複雜資料、特殊場景等,對測試異常情況造成困難,此時可以使用擋闆模拟特殊資料,進行相應測試。
● QA儀表盤:必要的品質監督環節可以提高開發、測試的QA意識,QA儀表盤是對流水線品質資料進行收集和統一展示的平台。盡管我們可以從SVN、Jenkins、Sonar上看到相應的資料,但它們基于分散的Job,無産品關聯資訊,且缺少統計類資料。為了更好地發揮品質監督作用,我們開發了QA儀表盤,将各個環節品質資料進行收集、加工、展示。
1)以産品為基本次元組織資料,并進行團隊、部門等不同層級的統計和展示。
2)提供郵件訂閱等個性化功能,友善使用者定期監督産品品質資料。
● 錯題本:顧名思義,這是一個記錄品質問題的平台。各個階段注入的問題(需求、開發、測試分析、測試實施、營運等)都可以納入這個平台,并進行詳細跟蹤記錄。測試經理也會定期從錯題本導出問題,組織品質問題分析會。通過及時記錄問題、分析問題,可以為以後的測試分析積累經驗,避免同類品質問題重複出現,減少日後“踩坑”的幾率。
開發測試融合與靈活實施是相輔相成的。從組織結構上看,将開發、測試團隊融于同一部門,其中測試團隊承擔部門的測試實施、品質管控、工藝改進(工具建設)工作;産品以靈活組為單元開展任務實施,靈活組裡包含PO、開發、測試,逐漸建立起一個全功能靈活虛拟團隊。通過這樣的組織調整,加強測試與開發的聯系,也增強靈活團隊的集體意識,有利于培養DevOps文化氛圍。
伴随着上述組織調整,測試團隊的職能也發生了改變。過去,測試團隊的主要任務是實施測試任務,測試經理們重點關注的是案例執行情況、測試流程等;而随着開發測試融合的推進,我們賦予了測試經理更多的話語權:測試經理承擔産品QA角色,從産品需求到投産階段結束,關注整個工程活動周期的品質問題,如使用者故事品質、單元測試情況、缺陷分析等,建立QA全流程品質控制機制。從這個角度講,測試經理要不斷提高自身能力,培養更全面的品質意識。
經過上述一系列提升和改進工作,App産品的傳遞效率有了明顯改善,各靈活小組的品質意識和CI意識也得到了顯著提升,DevOps的氛圍已經形成。
1、App産品的疊代速率明顯提高。得益于App持續傳遞流水線的有效實施,任務下達至完成時間明顯縮短。App持續傳遞工具、擋闆等工具得到了有效推廣,工具賦能對于開發、測試效率提升發揮了巨大作用。
2、疊代品質顯著提升。2018年以前,部門疊代成功率僅為70%,2019年已提升至93%。疊代過程中,持續傳遞流水線的建構成功率也保持在80%以上。
3、産品品質明顯提升。開發更加注重自己的代碼品質,并在QA的監督下關注自動化測試資料,進而使開發團隊的Bug數量明顯減少。自動化接口測試積累了大量案例,自動化單元測試覆寫率從無到有,從有到高,目前部分産品覆寫率已達90%以上。
本文介紹的實踐案例仍處于初級階段,App持續傳遞流水線還存在很大的提升空間。未來,計劃進一步優化持續傳遞流水線,擴充工具功能,深化DevOps實踐。