本文是我受邀在 TiD2019質(zhì)量競爭力大會區(qū)塊鏈論壇中的分享的一個主題,介紹如何運用 DevOps 技術(shù)體系讓開發(fā)和測試、運維進行高效協(xié)作,如何使用 CI/CD 進行區(qū)塊鏈軟件自動化測試、軟件發(fā)布;設(shè)計 CI/CD 流水線時需要注意哪些問題;區(qū)塊鏈軟件自動化測試有哪些難點;如何提高自動化測試運行效率;什么樣的測試報告才是好的報告;測試框架優(yōu)化實戰(zhàn)經(jīng)驗分享。
大綱
- 背景介紹
- DevOps 流程 - 需求、開發(fā)、測試、運維、監(jiān)控一體化
- 敏捷開發(fā)與DevOps - 開發(fā)和測試、運維應(yīng)該如何協(xié)作
- 為什么要自動化測試?
- 介紹CI/CD流水線
- 如何設(shè)計測試流水線
- 實戰(zhàn)經(jīng)驗:優(yōu)化流水線
- 實戰(zhàn)經(jīng)驗:優(yōu)化測試框架
背景介紹
為了提高軟件的研發(fā)效率、保證軟件質(zhì)量、高效服務(wù)運維,我們在開發(fā)管理上實踐敏捷開發(fā)、使用 DevOps 進行自動化運維、實行持續(xù)的自動化測試。
在介紹怎么做之前,先說下我們做了什么,這樣能比較好理解知道我們?yōu)槭裁匆@樣做。
我們在2016年開發(fā)了一款區(qū)塊鏈軟件 CITA,并在2017年進行了項目開源:https://github.com/cryptape/cita
CITA 是我們從頭開始自主研發(fā)的一個高性能區(qū)塊鏈內(nèi)核,具有微服架構(gòu)、水平擴展、組件可插拔、高性能這些特質(zhì)。
區(qū)塊鏈服務(wù)簡單可以看作是一種分布式的賬本同步系統(tǒng)。為了簡化應(yīng)用開發(fā)者的使用我們還開發(fā)了與之配套的各種開發(fā)、調(diào)試工具、組件,例如:
CITA內(nèi)核與各組件的關(guān)系圖:
這些工具都是開源的:https://www.citahub.com/#componentArea
具體怎么做
我們實踐 敏捷開發(fā)
我們使用敏捷開發(fā)中的 Scrum 框架管理團隊目標和進度。
敏捷開發(fā)的目標是通過迭代開發(fā)的方式交付可工作的軟件。
我們會將一個大的版本作為一個Milestone(里程碑),定義好必須要完成的總目標和時間點,然后切分成幾個較短工作周期的 Sprint(迭代),每個 Sprint 有自己要完成的階段目標。
我們使用 Story Point 來評估每個任務(wù)的完成時間,使用燃盡圖反饋任務(wù)完成進度,以便可調(diào)控每個 Sprint 的節(jié)奏和進度,如下圖,是我們一個子產(chǎn)品開發(fā)過程的各個Sprint 里的燃盡圖:
在具體的任務(wù)管理上我們使用 Kanban(看板)工具來跟蹤每個成員的任務(wù)狀態(tài),如下圖:
看板是一種圖形化的展示工具,由于人類天生對視覺化的信息更容易理解,通過它可以很直觀的反應(yīng)每個任務(wù)的狀態(tài)、同時也是一種工作量的直觀呈現(xiàn),讓開發(fā)組中每個成員都可以清晰知道自己、同時了解到其他人的工作進展。
我們實踐 DevOps
軟件開發(fā)不只是把代碼編寫出來就完事,還需要經(jīng)過測試保證完整性、把測試后的軟件部署到服務(wù)器上,還要設(shè)置監(jiān)控保障服務(wù)運行正常,并能收集反饋給產(chǎn)品、開發(fā)團隊對軟件功能、質(zhì)量進行持續(xù)的改善,才是一個完整可用的服務(wù)開發(fā)到上線的過程,整個過程如上圖所示,一環(huán)銜接一環(huán)。
我們?nèi)绾螌嵺` DevOps?
如上圖所示,DevOps 不單是運維團隊的事情,而是開發(fā)、運維、測試各種崗位人員一體化實施的一個過程。我們要求做到流程規(guī)范化,這樣各個職能成員能互相了解對方的工作輸出預(yù)期,才能高效協(xié)作。流程規(guī)范化后,才能使用工具進行自動化來提高工作效率和減少人為產(chǎn)生的故障。讓各環(huán)節(jié)的協(xié)作像是流水線般清晰可感知、可預(yù)期。
有人認為要實踐 DevOps 要要求團隊成員都是全棧工程師,而我認為專業(yè)分工才能深入和精通,因此我們把團隊分為區(qū)塊鏈開發(fā)、測試開發(fā)、運維開發(fā)團隊,注意到每個崗位都是有“開發(fā)“字眼,具備有編程能力的團隊才是能有效實踐 DevOps 的根本。
我給團隊設(shè)定3個目標:
開發(fā)區(qū)塊鏈軟件 - 軟件代碼 用 CI 進行自動化代碼質(zhì)檢、測試、構(gòu)建、發(fā)布
測試區(qū)塊鏈軟件 - 測試代碼 用 CI 進行冒煙、回歸、性能、穩(wěn)定性測試
運維區(qū)塊鏈服務(wù) - 監(jiān)控服務(wù) 用 CI 進行主動監(jiān)控、被動告警
對這樣的團隊的要求:
- 開發(fā)、測試、運維均要求有編程能力
- 開發(fā)、測試、監(jiān)控服務(wù)的代碼,均遵從相同的開發(fā)流程、使用CI工具
開發(fā)流程
使用 GitHub Flow 進行代碼管理, 本地創(chuàng)建 feature 分支 -> 發(fā)PR -> 代碼審查 / CI 檢查 -> 合并 master 分支:
自動化運維
使用 CI/CD 流水線 進行自動化構(gòu)建、測試、發(fā)布、部署:
開發(fā)人員的代碼開發(fā)完成會進行代碼審查、靜態(tài)代碼掃描檢查代碼規(guī)范和代碼安全檢查、運行自動化測試;根據(jù)不同的分支合并策略進行不同環(huán)節(jié)的自動化部署,如合并到 develop 分支會觸發(fā) staging 環(huán)境的部署,部署成功后自動通知測試人員進行驗收測試;合并到 master 分支會觸發(fā) production 環(huán)境的部署,部署成功后自動發(fā)送上線通知讓運營人員進行運營使用。 使用自動化的 CI/CD 工具和流程,可以把功能開發(fā)到上線時間,縮短到開發(fā)人員提交代碼的最后一刻,并且在 CI 服務(wù)上有記錄,每個人都能知道是什么人、在什么時候、部署了什么改動、到哪個環(huán)節(jié),提高了運維效率也減少了人工操作過程的人為事故可能性。
服務(wù)監(jiān)控
運維使用 ELK 服務(wù)進行日志收集、數(shù)據(jù)分析,如下圖,我們對 測試鏈 各個節(jié)點上服務(wù)的日志收集和分析,出現(xiàn)軟件故障時方便運維、開發(fā)人員了解原因。
為了方便CITA服務(wù)的運維,我們的運維團隊開發(fā)了 CITA 的監(jiān)控服務(wù),可用于監(jiān)控節(jié)點中CITA的服務(wù)運行情況,包括采集區(qū)塊鏈數(shù)據(jù)、CITA進程的存活監(jiān)控、運行環(huán)境監(jiān)控、故障自動告警通知,提供給開發(fā)、運維人員友好的可視化的面板,如下圖:
同樣的,這個監(jiān)控工具的本身的開發(fā)流程也是一樣遵從同樣的 DevOps 實踐,同樣也是開源的:https://github.com/cryptape/cita-monitor
持續(xù)自動化測試
提高了開發(fā)、運維效率,還要保障軟件的質(zhì)量,這個是我們測試團隊的工作重點。
下圖是軟件測試中著名的測試金字塔,測試金字塔說明了一種兩難的境地:越是上層的測試,就會耗費越多的精力、時間和成本。
我們的測試團隊的工作重點正是最耗時間、資源的系統(tǒng)測試的自動化。這并不是說開發(fā)團隊就不用管測試了,開發(fā)團隊主要編寫單元測試、集成測試等的白盒測試。
因為我們認為:
- 自動化測試才能讓QA的價值最大化;
- 自動化需要 CI 工具來做管理和執(zhí)行。
區(qū)塊鏈軟件是一種多實例運行的系統(tǒng),只保障了單元測試、集成測試的結(jié)果是遠不足夠保障系統(tǒng)最終是可用、結(jié)果是可信的,而區(qū)塊鏈又是一個用計算機軟件解決【信任】的工具,軟件首先必須是可信的,產(chǎn)生的數(shù)據(jù)才能讓人信任,因此我們對測試工作投入大量的精力來保障軟件的質(zhì)量。
我們做的系統(tǒng)測試是一種端對端級別的、在仿真環(huán)境中軟件運行結(jié)果的黑盒測試,為了提高測試工作效率,我們使用了 CI 流水線來管理多種測試策略。
測試流水線
什么是 CI/CD 流水線(Pipeline)?
如下圖所示,Jenkins 是我們使用的 CI 工具之一,一條 CI/CD Pipeline 像是一個的管道,代碼提交后會觸發(fā) CI 的運行策略,執(zhí)行自動化的構(gòu)建、測試從而實現(xiàn)持續(xù)集成或持續(xù)部署流程,不同管道環(huán)節(jié)有各自的輸入、輸出,任何一個環(huán)節(jié)出問題都阻塞影響到整個管道的工作。
進行 CI/CD 流水線設(shè)置之前,先思考3個問題:
- 如何設(shè)計一條合理的流水線?
- 如何設(shè)計測試流水線?
- 為什么要設(shè)置多條流水線?
流水線設(shè)計關(guān)鍵要素有2點:
- 設(shè)計合適的Workflow:工作流程,如:stage 1 -> stage 2 -> stage 3
- 設(shè)計Workflow 中的 Stage Job:階段工作,如:unit-test, build, integration-test, code-audit, staging-deploy, production-deploy
每個 Stage Job 也有5個設(shè)計關(guān)鍵要素:
- Up/Down stream:上下游的Stage Job
- Trigger: 觸發(fā)條件
- Input/Output:輸入?yún)?shù);輸出構(gòu)件產(chǎn)物、輸出參數(shù)
- Steps:執(zhí)行步驟
- Notification:結(jié)果通知;最后的 stage 都要有明確的通知對象
我們都知道做軟件開發(fā)需要有 PRD(功能需求文檔),同樣的流水線設(shè)置也需要有設(shè)計文檔。
在設(shè)置具體的 CI/CD 流水線前,要做下流水線設(shè)計,如下圖是我們其中2條流水線的設(shè)計文檔:
設(shè)計好各種流水線的作用、執(zhí)行策略和運行步驟細節(jié)后,就可以在 CI 工具上進行相應(yīng)的設(shè)置,不要一邊想一邊改 CI 配置,特別是對于復(fù)雜的流水線應(yīng)該設(shè)計好再做設(shè)置,這樣一來流水線自己也有了文檔留存,方便其他運維同事協(xié)作,開發(fā)和測試也能清楚工作流程。
如下圖,是我們設(shè)置的發(fā)版測試流水線:
發(fā)版測試流水線分為4個階段:
- 構(gòu)建測試對象:獲取軟件代碼,自動編譯生成不同算法版本的二進制文件bin
- 生成測試運行環(huán)節(jié):把 bin 文件放入可運行的環(huán)境,構(gòu)建 Docker Image
- 運行測試用例:對不同 bin 版本運行自動化測試用例;并行執(zhí)行節(jié)省時間
- 生成測試報告:自動匯總各個版本的測試結(jié)果,自動生成一份包含測試對象、測試環(huán)境、測試結(jié)果的報告;并自動把構(gòu)建產(chǎn)物存檔,方便對外發(fā)布
多種流水線策略
發(fā)版流水線無疑是我們?nèi)粘i_發(fā)中最重要的一種流水線,為了能讓開發(fā)人員盡早發(fā)現(xiàn)代碼質(zhì)量問題,我們還設(shè)置各種策略的測試流水線,例如用于保障開發(fā)主分支的系統(tǒng)測試流水線、用于保障測試代碼質(zhì)量的冒煙、回顧測試流水線;用于保障軟件性能的性能測試流水線等。
- 系統(tǒng)測試流水線:
- 當開發(fā)人員在開發(fā)的 develop 分支有合并時執(zhí)行全量測試用例集的回歸測試,用于保障開發(fā)主分支的代碼質(zhì)量。
- 冒煙測試流水線:
- 用于做測試用例的增量,用于保障測試代碼的代碼質(zhì)量;當測試人員提交測試代碼的 feature 分支時執(zhí)行;只運行 P1 級別的測試用例集,執(zhí)行速度快,加快代碼審查、合并流程;復(fù)用由發(fā)版流水線生成的測試對象。
- 回歸測試流水線:
- 用于保障測試代碼的代碼質(zhì)量;當測試人員合并測試代碼的 develop 分支時執(zhí)行;運行全量的測試用例集,執(zhí)行速度慢,但避免引入有破壞性的代碼;同樣是復(fù)用由發(fā)版流水線生成的測試對象。
其他測試流水線:
- 性能測試流水線:
- 除了保障軟件的可用性,我們非常關(guān)注軟件的運行效率,因此我們設(shè)置了性能測試流水線。性能測試關(guān)注的結(jié)果是一些性能指標,如反映服務(wù)處理能力的TPS、延遲和響應(yīng)時間等。但性能測試的運行代價很高,需要獨占主機資源并長時間運行。因此我們設(shè)置成每天晚上凌晨2點半自動運行性能測試流水線,運行完畢會生成圖形化的報告發(fā)送郵件通知開發(fā)團隊。這樣開發(fā)團隊每天都能了解到主分支的性能變化情況,當出現(xiàn)有重大性能變化時可以及早進行優(yōu)化修復(fù),而不是等到發(fā)版測試階段才知道結(jié)果。
- 穩(wěn)定性測試流水線:
- 我們還關(guān)注軟件的穩(wěn)定性,軟件的穩(wěn)定性是指在服務(wù)有大量請求壓力時各種關(guān)鍵功能還能正常工作。因此我們設(shè)置了穩(wěn)定性測試流水線,在發(fā)版階段執(zhí)行,可以按需要選擇壓測的參數(shù)。
- 可用性測試流水線:
- 開發(fā)人員做了一些重大改動,在合并到主分支前,想了解是否有其他副作用,因此運維提供了可用性測試流水線,開發(fā)自己選擇需要測試的分支執(zhí)行即可獲得該分支回歸測試的結(jié)果。
- 性能改進測試流水線:
- 開發(fā)人員做了一些性能相關(guān)的改動,想了解整體上的性能變化,運維提供了性能改進測試流水線,開發(fā)自己選擇需要測試的分支執(zhí)行即可獲得該分支的性能測試結(jié)果。
在DevOps 模式的協(xié)作重點
在 DevOps 模式下開發(fā)、測試、運維人員的協(xié)作重點為:
- 運維的工作目標是使用自動化技術(shù)為開發(fā)、測試提供便利流程、工具,減少重復(fù)工作
- 測試的工作目標是使用自動化技術(shù)提高測試效率、保障開發(fā)成果質(zhì)量
- 開發(fā)享受自動化的便利,專心做開發(fā),提高軟件質(zhì)量
沒有自動化則沒有效率提升和質(zhì)量持續(xù)保障,而自動化工具的維護當然也是有代價的,這個正就是實踐 DevOps 的團隊真正要做的工作。
實戰(zhàn)經(jīng)驗分享
如何優(yōu)化流水線和測試框架,以下是我們實踐的一些技巧和收獲:
流水線優(yōu)化技巧
- 流水線互相制約保障質(zhì)量
系統(tǒng)測試流水線保障開發(fā)代碼質(zhì)量
回歸測試流水線保障測試代碼質(zhì)量
-
配合 GitHub Flow 約定自動化觸發(fā)規(guī)則:
feature 分支跑冒煙,冒煙過了合并到 develop
合并 develop 跑回歸,回歸過了合并到 master
-
重用測試對象:
發(fā)版測試構(gòu)建測試對象
冒煙、回歸使用已構(gòu)建的測試對象
測試對象放入Docker Image 做版本管理,本地測試和CI上使用相同測試對象
存檔構(gòu)建工件
合并測試報告
測試環(huán)境使用 Docker Container 隔離
每條測試用例隔離運行
測試框架優(yōu)化技巧
- 使用環(huán)境變量及 Docker Image Tag 獲取測試對象
- 使用 Docker Image 獲得統(tǒng)一的測試環(huán)境
- 出錯自動重試用例
- 測試用例并行執(zhí)行
- 管理輸出日志
- 輸出直觀的測試報告
什么樣的測試報告才是好的報告?
測試工作的最終呈現(xiàn)結(jié)果就是測試報告,那什么樣的測試報告才是好的報告?
我認為一份清晰準確的測試報告總結(jié)內(nèi)容應(yīng)該包含:
-
測試對象
- 軟件名稱
- 軟件版本
- 源碼地址
- 源碼commit id
- bin文件輸出的版本信息
-
測試環(huán)境
- 測試代碼的commit id
測試用例
測試結(jié)果
而一個好的測試框架應(yīng)該能幫助測試人員自動生成這樣一份測試報告,提高測試人員的工作效率和準確性。
以下就是我們使用的測試框架(使用 TestNG 作為基礎(chǔ)框架)得到的報告:
我們對測試框架持續(xù)改良,使得自動生成測試報告中能輸出我們關(guān)注的測試對象版本、測試環(huán)境、測試代碼版本等信息,收到測試報告通知時,每個人都在通過報告可以清晰并準確知道測試的是什么、是什么結(jié)果、怎么測試的。
我認為企業(yè)協(xié)作的高效秘訣之一是:Don't ask, look by your self! (不用問,自己看)
可以主動感知的信息才有效率,通過詢問才能得知是低效的工作方式。
以上便是我們對區(qū)塊鏈軟件的工程質(zhì)量控制的一些經(jīng)驗分享,請注意,每個企業(yè)都有各自的優(yōu)勢、短板或歷史包袱,經(jīng)驗不能復(fù)制只能參考,適合自己的才是最好的,謝謝。