1. 程式人生 > 其它 >微服務測試的思考與實踐

微服務測試的思考與實踐

最近幾年,微服務架構越來越火爆,逐漸被企業所採用。隨著軟體架構的變化,對應的軟體測試策略需要作何調整呢?本文將介紹微服務架構下的測試策略,並結合分享在業務和架構演變過程中,一個歷經九年的專案測試策略的演進。

關於微服務

微服務架構是一種架構模式,它提倡將單一應用程式劃分成一組小的服務,每個服務執行在其獨立的程序中,服務間採用輕量級通訊機制互相溝通(通常是基於HTTP協議的RESTful API)。每個服務都圍繞著具體的業務進行構建,並且能夠被獨立部署到生產環境、預生產環境。

從微服務的概念可以看出它有如下好處:

  • 每個服務可以獨立開發
  • 處理的單元粒度更細
  • 單個服務支援獨立部署和釋出
  • 更有利於業務的擴充套件

同時,獨立開發導致技術上的分離,HTTP通訊加上Queue的機制增加了問題診斷的複雜度,對系統的功能、效能和安全方面的質量保障帶來了很大的挑戰。另外,服務間的複雜依賴關係帶來了很多的不確定性,要實現獨立部署,對運維也提出了更高的要求。微服務架構的系統要特別關注這幾個方面:

  • 服務間的依賴、連通性
  • 服務的容錯、可用性
  • 資料的最終一致性
  • 獨立部署
  • 不確定性

測試策略的選擇

談到微服務的測試策略,很容易就想到了老馬推薦的文章《Microservices Testing》,該文推薦的微服務框架下的測試策略是這樣的:

(經典策略模型)

這個策略模型強調測試分層以及每一層的恰當覆蓋,整體符合金字塔結構。它是最優的嗎?

有人對此提出了質疑...認為策略模型應該是蜂巢形狀的(請參考文章):

(蜂巢模型)

這個模型重點關注服務間的整合測試,兩端的單元測試和UI層E2E測試較少。

也有同事提出微服務下的測試結構應該是鑽石形狀的,服務間的整合依然是重點,單元測試較少,而頂層增加了安全和效能等非功能測試。

(鑽石模型)

好像都有道理,到底選擇什麼樣的策略模型好呢?不禁陷入了困境…...怎麼辦?不妨先來聽聽我們專案的故事吧!

專案的故事

測試策略的演進

還是那個藍鯨專案,不知不覺進入了第九個年頭。在這九年裡,隨著業務的不斷髮展,系統架構也進行了多次演進和調整。相應的,測試策略也發生了有意思的演進變化。

(測試策略的演進)

最初單一使用者系統、單體架構的時候,嚴格按照測試金字塔來組織各層的自動化測試。隨著功能的擴充套件,大量mock的單元測試給重構帶來了很大的不便。

企業系統開始開發的時候,我們調整了策略,減少單元測試的編寫,增加UI層E2E測試的覆蓋,測試結構由原來的金字塔演變成上面梯形下面倒三角的形式。

後來,架構調整,開始服務化。此時,大量的E2E測試漸漸暴露出問題:

  • CI上的測試執行時間越來越長,而且定位問題的能力很弱,測試買二手手遊賬號平臺地圖一旦失敗需要很長時間修復,測試人員好幾天也拿不到可以測試的版本,反饋週期過長;
  • 由於服務化帶來的不穩定因素增加,E2E測試沒法很好的覆蓋到需要的場景,測試人員就算拿到可測的版本也總有各種缺陷發生。

因此,專案引入契約測試,停止編寫新的E2E測試,將測試下移,分別用API測試和契約測試取代。

隨著功能的不斷增加,雖然E2E測試的量並不增加,但是其不穩定性、維護難、定位難的問題有增無減,此時已經很難由自動化測試來保證產品的質量。為了平衡成本和收益,專案考慮去掉大部分E2E測試,只保留少量的Smoke測試,將更多的測試下移。

同時,技術雷達上新的技術“生產環境下的QA”出現,專案也開始關心生產環境,並且在QA測試階段結合微服務的特點進行對應的探索式測試。

應對微服務的挑戰

前文提到過微服務帶來的挑戰,下面來看專案是如何應對這些挑戰的。

服務間的依賴、連通性

微服務架構下,獨立開發的服務要整合起來最具挑戰,如何保證服務間的依賴關係和連通性非常關鍵。前面已經講過E2E整合測試有很大的挑戰,並不適合,而消費端驅動的契約測試是個不錯的選擇。專案正是利用契約測試去保證服務間的連通性,取代一部分E2E整合測試。

服務的容錯、可用性

在系統負荷達到一定程度或者某個服務出現故障的時候,微服務架構有兩種技術來確保系統的可用性:服務的熔斷和降級。服務的熔斷是指當某個服務出現故障時,為了保證系統整體的可用性,會關閉掉出現故障的服務;服務的降級則是當系統整體負荷過載的時候,考慮關閉某些外圍服務來保證系統的整體可用性。

對應的測試包括:

  1. 熔斷:從效能角度,當系統負載達到某個熔斷狀態的時候,服務是否能正確熔斷;同時,從功能角度驗證熔斷後系統的行為是否跟預期相符;
  2. 降級:從業務的角度,要能區分出核心業務和外圍業務,在需要降級的時候不能影響核心業務;當某個服務降級後,從功能角度驗證系統行為是否跟預期相符。

資料的最終一致性

(資料一致性)

資料一致性是微服務特別需要關注的。舉個例子,電商平臺某個訂單支付成功以後,需要更新積分和訂單狀態,當訂單服務或者積分服務其中有一個出現故障的時候,就會導致最終的資料不一致性。

測試這種情況,從業務的角度分析哪些服務會導致資料不一致性,製造對應的異常情況去測試資料的最終一致性。

獨立部署

微服務的獨立部署需要有CI、CD的支援,跟DevOps實踐分不開。同時,更為關鍵的是需要契約測試來驗證獨立部署後服務行為的正確性。專案在這方面的工作,請參考王健的文章:你的微服務敢獨立交付嗎?

不確定性

微服務架構使得系統複雜度增加不少,很多的事情發生都是不可預測的,只能在其發生以後找到產生的原因。因此,也就沒法在預生產環境通過測試去發現在真實生產環境才會發生的issue,我們需要把目光轉移到生產環境,利用生產環境的不確定性、微服務的不可預測性來構建反脆弱的系統。

專案在這方面主要採用的技術是生產環境下的QA,請參考文章:生產環境下的QA

專案測試策略

從前面介紹的演進過程可以看到,專案測試策略在不同階段結合參考了不同的策略模型:金字塔->近似鑽石(除非功能測試外,類似於鑽石模型)->蜂巢。後期全面服務化的時候,我們認為蜂巢模型是比較適合的。

當然,光有符合這個策略模型的自動化測試是遠遠不夠的,我們專案還採用了針對微服務特點的探索式測試,保持持續交付節奏,踐行DevOps實踐,結合生產環境下的QA等技術把關注點右移到生產環境。

現在,專案整體測試策略演變成下圖的形式:

(專案測試策略)

  1. 專案採用的是敏捷迭代開發和持續交付的模式,每四周一個釋出週期。
  2. 在開發過程中實現的自動化測試是分層實現的:底層少量的單元測試,中間量最多的是API測試(類似於老馬策略模型裡的元件測試),上面有一部分契約測試和少量的Smoke測試來保證服務間的契約和整合。除此之外,QA有手動的探索式測試,其中包括針對微服務特點進行的一些測試。整個測試結構是類似於蜂巢模型的。
  3. 採用生產環境下的QA技術,利用生產環境,進行error監控、使用者行為分析、使用者反饋收集,從而來影響和指導預生產環境的開發和測試工作。
  4. 利用DevOps實踐,做到高效的部署和監控,跟生產環境下的QA結合,形成良性的環路,保證專案的正常交付。

測試策略再思考

專案上多次測試策略的調整,看似很簡單,其實每次調整並不是一個輕鬆的過程,都是平衡利弊、綜合考慮多個因素才做出的決定。

分析整個調整過程,最後突然發現:當我們面對多個策略模型不知道如何選擇的時候,其實我們陷入了一個太過於關注測試結構的誤區,忘記了最初的目標是什麼。

影響測試策略的因素

跳出誤區,回到原點,重新思考測試策略的目標。影響策略的最關鍵因素是業務價值、質量要求、痛點。

(影響測試策略的因素)

業務價值

帶來更大的業務價值、幫企業贏得更多的利潤,是軟體系統的目標;軟體測試是軟體系統成功的保障之一,業務價值也是測試策略的終極目標。所有測試活動都要圍繞這個目標開展,考慮業務優先順序,有效規避業務風險。

質量要求

不同的系統、同一系統的不同利益干係人(參與的不同角色)對於質量的定義和要求都可能是不同的,這毫無疑問是影響測試策略的一個關鍵因素。

對於僅有內部使用者的系統,關注的重心可能是系統的功能;而對外發布的產品,則要求更高,一個按鈕位置的不恰當都可能帶來大量使用者的流失。

痛點

真正的痛點往往也是優先順序最高,迫切需要解決的。那些可以通過測試策略的調整來解決的痛點,自然成為了關鍵的影響因素之一。比如,CI Pipeline出包太慢,為了提高出包的效率,一方面在Pipeline本身想辦法,另一方面調整自動化測試的比例、執行頻率等也是解決方案之一。

演進式測試策略

處在不同階段的專案,在業務價值這個大目標下,其他影響因素也是會不一樣的,跟技術架構的演進一樣,測試策略也應該是演進式的。

從目標出發,綜合所處階段各個方面的影響因素,制定出適合當時的測試策略。隨著時間的推移,對策略進行評估和度量,並進一步改進、提高,以更好的滿足需求。這就是目標驅動的演進式測試策略。

(演進式測試策略)

總結

微服務架構下多個服務的整合是最具有挑戰的,對此最重要的是契約測試。契約測試有效保證服務間的契約關係不被破壞,確保服務的連通性,有助於實現真正的獨立部署和獨立交付。

微服務架構引入的不確定性並不是壞事,可以利用這些不確定性,採用生產環境下的QA等技術,增強系統的反脆弱性,從中獲益。

測試策略的影響因素不是唯一的,技術架構並不是最關鍵的因素。微服務架構下的測試策略跟其他架構下的並不會有本質的區別。

業務價值始終是我們的終極目標。在這個終極目標的驅動下,測試策略不是制定完了就可以束之高閣的,需要在整個軟體系統構建過程中不斷的度量和改進,是演進式的。