持續整合 測試三角形與分段構建策略原則

2021-08-27 15:04:29 字數 3733 閱讀 8943

《infoq》

隨著軟體產品新特性的不斷增加,軟體自動化測試用例的數量也會成倍增長。對於一些歷史「悠久」的遺留系統來說,甚至會積累數以萬計的自動化測試用例。如果對這樣的系統進行持續整合,還要求每個開發人員都要進行本地驗證的話,困難的確不小。讓我們還是看看joe的團隊是如何解決類似問題的吧。

在《戲說checkin dance》一文 中,咱們說到:joe?的團隊實施了帶有令牌的持續整合提交流程紀律。由於每個人都做本地構建進行驗證後再提交,所以持續整合平台上的構建結果比較穩定,每天持續整合伺服器上的構建最多只有 一兩次失敗(常見的原因是忘記提交某個檔案而導致失敗,和因本地環境配置與平台環境配置不一致而導致失敗),但一般都能在30分鐘內修復。隨著專案的進 行,新功能不斷地增加,自動化測試用例也越積越多。由於不做任何修改,本地構建指令碼就會執行所有自動化測試用例,所以本地構建的執行時間也越來越長。團隊裡有人開始抱怨,「每次提交**前,執行本地構建都超過15分鐘,這樣太浪費時間。我們可否把那些不太重要的測試拿出去,不再執行了?」

一、自動化測試**三角形

作為團隊的技術負責人,joe把大家叫到一起,就這個問題進行了專門的討論。

「我們不能放棄執行這些測試。」alice說道,「在我前乙個專案中,我們就是這麼做的,結果,這些花精力寫的測試都作廢了。」

「那是為什麼呢?」?bob問道。

alice回答道:「因為並不經常執行這些測試,隨著功能的修改,有些測試的邏輯就不再是正確的了。而當再次執行發現這類問題時,通常的結果就是把這個測試刪掉,因為修復這個測試的工作量太大了。」

「那持續執行所有測試的話,等待的時間太長了,也是一種浪費呀。?」bob說道。

此時,作為團隊技術負責人的joe說話了。「讓我們先分析一下,到底有哪些什麼原因讓我們的測試在這麼短的時間裡就變成需要這麼長時間了呢?」

「功能增加的多了,測試自然就多了唄。」

「功能增加了,自動化測試資料的準備工作也多了,需要的時間當然就長了。」

「現在我們的測試中有很多地方需要測試在原地等待結果返回,所以等待時間也挺長的。」

「大家還有沒有其它原因?」joe追問道。

「那好吧。功能多而導致測試多這是好事兒,說明我們大家都非常重視我們的自動化測試。對於『測試準備時間變長』這個問題可以理解,因為我們的產品越來越複雜了。對於『結果返回的等待問題『嘛,需要具體問題,具體分析。前幾天,我看到乙個『測試**三角形』,講的就是自動化測試中各類測試的應具有的比例關係,對我很有啟發。我在白板上畫一下吧。」於是,joe走到白板前,將這個測試**三角形畫了下來,如圖1所示。

然後,joe將這個圖形解釋了一下。原來,這個三角形講的就是單元測試、整合測試和驗收測試的關係。首先,左邊向上的箭頭表示,越高層次的測試維護成本越高,執行時間越長。因此,對於單個測試來說,單元測試執行最快,維護最容易,而整合測試次之,驗收測試則最高。?每類測試的面積代表著該測試的數量。現在,業界有很多種工具支援單元測試,因此它的編寫及維護成本相對其它兩種測試來說較低,應使用單元測試對**做盡可能多的測試覆蓋。一般來說,單元測試覆蓋率達到70~80%是比較理想的狀態。

alice說道:「那要看你怎麼定義單元測試中的這個單元。」

「根據wikipedia上的定義,乙個單元是指應用程式中最小可測試的部分。既然我們使用物件導向的開發語言c++,那麼單元測試的粒度應該是類中的乙個方法吧。而且,通常來說,如果乙個測試包括以下任何乙個情形,它就不是乙個單元測試:(1)需要連線資料庫;(2)需要網路通訊;(3)需要與檔案系統打交道;(4)不能和其它單元測試同時執行;(5)需要對環境進行一些配置(如編輯配置檔案)才能執行它。」joe回答道。

「要是這麼說的話,我們的測試中,一部分是模組整合測試,一部分是驗收測試,只有一小部分算是單元測試。我們的測試集合正好是乙個倒三角。」bob邊說,邊在白板上畫了出來,如圖2所示。

「既然高層次上的測試(整合測試和驗收測試)維護量比較大,今後我們應該加入更多的低層次測試(單元測試),對於關鍵功能進行整合測試和驗收測試。如果對於測試用例具有等價性的話,我們應該用低層次測試來實現。這樣我們就會達到自動化測試的**三角狀態啦。」joe邊說邊在白板上筆劃著,如圖3所示。

「我同意你說法,但是仍舊沒有解決我們目前遇到的問題。如何解決我們現在本地構建時間太長的問題呢?」alice有點兒不耐煩地問道。

二、分階段構建?

「這還不容易,martin folwer(敏捷宣言的創造者之一)已經給出了乙個解決方案,那就是兩階段構建(secondary build)。也就是說,我們可以把那些執行比較慢,時間比較長且基本上不會失敗的自動化測試用例挑選出來,組成乙個新的測試集,在第二階段執行,可以叫做『二級構建階段』。剩餘的測試集仍舊放在第乙個階段執行,我們可以把第乙個階段叫做『提交構建階段』。」joe回答道。

「那什麼時間執行這兩個階段的構建呢?」bob問道。

「提交階段構建當然就是在我們每個人提交之後就執行啦。而且在我們提交之前,作為本地驗證集合,在我們開發環境上也要執行同樣的提交構建。一般來說,本地構建和提交構建最好都在五分鐘內完成,最長也不要超過十分鐘,否則開發人員就不願意花時間做頻繁地**提交啦。另外,一旦提交階段構建成功以後,就馬上自動觸 發第二階段構建。而我們開發人員在持續整合伺服器上的提交階段構建成功以後,就可以繼續進行其它的工作啦。」joe說道,「我們原來的六步提交圖就變成這 個樣子了。」說著,joe拿起白板筆就畫了出來,如圖4所示。

「不對,這裡有問題!持續整合強調盡早反饋。如果把測試分成兩個階段了,那反饋週期不是加長了 嗎?」bob反駁道。

joe 點點頭,說道:「你說的沒有錯。但是,根據我們現有的軟硬體資源條件,我們目前還無法通過增加資源的方式來縮短所有測試執行的時間。所以我們必須在質量與速度之前做出平衡。這也是我為什麼要把那些不易出錯的自動化測試集合放在第二階段構建的原因,這樣可以降低但不能完全解除第二階段構建失敗的風險。所以, 這也要求我們大家當第二階段構建失敗時,也要找人盡快把它解決,並且把相關的測試再次放回提交測試階段中執行,或者在提交測試階段加入新的測試來補充。」 ?

alice此時插話,問道:「既然第二階段構建不常失敗,為什麼我們不定時執行它,比如每天晚上執行一次呢?這樣不是更節省資源嗎?另外,如果第二階段構建執行得慢,那它不是一直都落後嗎?」

「因為每次提交階段構建成功以後就觸發第二階段構建,這樣無論如何都比每天晚上執行一次的更多的反饋。因為每天晚上執行一次的話,如果出了問題,我們只能在第二天早上才能發現。對於你的第二個問題,我畫一張圖來解釋。」joe找了一張大白紙,在上面開始畫了起來。

當版本123的第二階段構建被觸發並正在執行,alice又提交了一次,觸發了版本124的提交構建;

當版本124的提交構建完成之後,由於版本123的第二階段構建仍在執行,所以不再觸發第二階段構建;

當版本125的提交構建完成時,版本123的第二階段構建仍舊在執行,所以也不觸發第二階段構建;

當版本126提交構建正在執行時,版本123的第二階段構建剛完成,此時由於版本125的提交階段構建是乙個最近 成功完成的提交構建,所以持續整合伺服器就會啟動該版本的第二階段構建,而忽略版本124的提交構建。

「那根據我們持續整合紀律,誰的提交讓構建失敗,就由誰來修復。如果版本125的第二階段構建失敗了,就包括版本124和125兩次提交的變更,由誰來修復呢??」bob接著問道。

「這個好辦,由這兩個提交人一起負責修復。如果想確切找到誰的提交有問題,還可以手動觸發版本124的第二次構建。假如構建成功,說明版本125有問題,假如構建失敗,說明問題在版本124就引入了。」alice搶著說道。

討論到這裡,團隊成員都達成了共識,(1)開始加強單元測試的力度;(2)在反饋速度和反饋質量之間做出折衷,使用二級構建構建的方式。

整個產品的開發非常順利,馬上就要進行版本發布了。團隊還會遇到什麼問題呢?他們是如何解決的呢?請聽下回分解。

持續整合 測試三角形與分段構建策略原則

infoq 隨著軟體產品新特性的不斷增加,軟體自動化測試用例的數量也會成倍增長。對於一些歷史 悠久 的遺留系統來說,甚至會積累數以萬計的自動化測試用例。如果對這樣的系統進行持續整合,還要求每個開發人員都要進行本地驗證的話,困難的確不小。讓我們還是看看joe的團隊是如何解決類似問題的吧。在 戲說che...

持續整合之「測試三角形與分段構建策略原則」

隨著軟體產品新特性的不斷增加,軟體自動化測試用例的數量也會成倍增長。對於一些歷史 悠久 的遺留系統來說,甚至會積累數以萬計的自動化測試用例。如果對這樣的系統進行持續整合,還要求每個開發人員都要進行本地驗證的話,困難的確不小。讓我們還是看看joe的團隊是如何解決類似問題的吧。在 戲說checkin d...

圓與三角形(圓與三角形是否相交)

給出圓的圓心和半徑,以及三角形的三個頂點,問圓同三角形是否相交。相交輸出 yes 否則輸出 no 三角形的面積大於0 第1行 乙個數t,表示輸入的測試數量 1 t 10000 之後每4行用來描述一組測試資料。4 1 三個數,前兩個數為圓心的座標xc,yc,第3個數為圓的半徑r。3000 xc,yc ...