微服務測試-服務測試(component/api)測試


==============摘自:倔強的瀟灑小姐 https://www.jianshu.com/p/df698a8f302a===================

微服務架構下,API 測試的最大挑戰來自於龐大的測試用例數量,以及微服務之間的相互耦合。



題外話
為了掌握微服務模式下的 API 測試,需要先了解微服務架構(Microservice Architecture)的特點、測試挑戰;而要了解微服務架構,又需要先了解一些單體架構(Monolithic Architecture)的知識。



單體架構(Monolithic Architecture)

單體架構是將所有的業務場景的表示層、業務邏輯層和數據訪問層放在同一個工程中,最終經過編譯、打包,並部署在服務器上。

比如,經典的 J2EE 工程,它就是將表示層的 JSP、業務邏輯層的 Service、Controller 和數據訪問層的 DAO(Data Access Objects),打包成 war 文件,然后部署在 Tomcat、Jetty 或者其他 Servlet 容器中運行。

優點:發布簡單、方便調試、架構復雜性低
缺點:
1、靈活性差
無論是多小的修改,哪怕只修改了一行代碼,也要打包發布整個應用。更糟糕的是,由於所有模塊代碼都在一起,所以每次編譯打包都要花費很長時間。
2、可擴展性差
在高並發場景下,無法以模塊為單位靈活擴展容量,不利於應用的橫向擴展。
3、穩定性差
當單體應用中任何一個模塊有問題時,都可能會造成應用整體的不可用,缺乏容錯機制。
4、可維護性差
隨着業務復雜性的提升,代碼的復雜性也是直線上升,當業務規模比較龐大時,整體項目的可維護性會大打折扣。

微服務架構(Microservice Architecture)

微服務是一種架構風格。在微服務架構下,一個大型復雜軟件系統不再由一個單體組成,而是由一系列相互獨立的微服務組成。
其中,各個微服務運行在自己的進程中,開發和部署都沒有依賴。

不同服務之間通過一些輕量級交互機制進行通信,例如 RPC、HTTP 等,服務可獨立擴展伸縮,每個服務定義了明確的邊界,只需要關注並很好地完成一件任務就可以了,不同的服務可以根據業務需求實現的便利性而采用不同的編程語言來實現,由獨立的團隊來維護。

 
單體架構 VS 微服務架構.png

特點:
1、每個服務運行在其獨立的進程中,開發采用的技術棧也是獨立的;
2、服務間采用輕量級通信機制進行溝通,通常是基於 HTTP 協議的 RESTful API;
3、每個服務都圍繞着具體的業務進行構建,並且能夠被獨立開發、獨立部署、獨立發布;
4、對運維提出了非常高的要求,促進了 CI/CD 的發展與落地。

微服務架構下的測試挑戰
由於微服務架構下,一個應用是由很多相互獨立的微服務組成,每個微服務都會對外暴露接口,同時這些微服務之間存在級聯調用關系,也就是說一個微服務通常還會去調用其他微服務。

鑒於以上特點,微服務架構下的測試挑戰主要來自於以下兩個方面:
1、過於龐大的測試用例數量
在傳統的 API 測試中,我們的測試策略通常是:

  • 根據被測 API 輸入參數的各種組合調用 API,並驗證相關結果的正確性;
  • 衡量上述測試過程的代碼覆蓋率;
  • 根據代碼覆蓋率進一步找出遺漏的測試用例;
  • 以代碼覆蓋率達標作為 API 測試成功完成的標志。

假設我們采用單體架構開發了一個系統,這個系統對外提供了 3 個 Restful API 接口,那么我們的測試策略應該是:

  • 針對這 3 個 API 接口,分別基於邊界值和等價類方法設計測試用例並執行;
  • 在測試執行過程中,啟用代碼覆蓋率統計;
  • 假設測試完成后代碼行覆蓋率是 80%,那么我們就需要找到那些還沒有被執行到的 20% 的代碼行。
    比如圖 中代碼的第 242 行就是沒有被執行到,分析代碼邏輯后發現,我們需要構造“expected!=actual”才能覆蓋這個未能執行的代碼行;
 
基於代碼覆蓋率指導測試用例設計的示例.png
  • 最終我們要保證代碼覆蓋率達到既定的要求,比如行覆蓋率達到 100%,完成 API 測試。

而當我們采用微服務架構時,原本的單體應用會被拆分成多個獨立模塊,也就是很多個獨立的 service,原本單體應用的全局功能將會由這些拆分得到的 API 共同協作完成。

比如,對於上面這個例子,沒有微服務化之前,一共有 3 個 API 接口,假定現在采用微服務架構,該系統被拆分成了 10 個獨立的 service,如果每個 service 平均對外暴露 3 個 API 接口,那么總共需要測試的 API 接口數量就多達 30 個。

如果我還按照傳統的 API 測試策略來測試這些 API,那么測試用例的數量就會非常多,過多的測試用例往往就需要耗費大量的測試執行時間和資源。

但是,在互聯網模式下,產品發布的周期往往是以“天”甚至是以“小時”為單位的,留給測試的執行時間非常有限,所以微服務化后 API 測試用例數量的顯著增長就對測試發起了巨大的挑戰。這時,我們迫切需要找到一種既能保證 API 質量,又能減少測試用例數量的測試策略。

2、微服務之間的耦合關系
微服務化后,服務與服務間的依賴也可能會給測試帶來不小的挑戰。

如圖所示,假定我們的被測對象是 Service T,但是 Service T 的內部又調用了 Service X 和 Service Y。此時,如果 Service X 和 Service Y 由於各種原因處於不可用的狀態,那么此時就無法對 Service T 進行完整的測試。

 
API 之間的耦合示例.png

方法:將 Service T 的測試與 Service X 和 Service Y 解耦

解耦的方式通常就是實現 Mock Service 來代替被依賴的真實 Service。實現這個 Mock Service 的關鍵點就是要能夠模擬真實 Service 的 Request 和 Response。

基於消費者契約的 API 測試
核心思想是:只測試那些真正被實際使用到的 API 調用,如果沒有被使用到的,就不去測試。

假設圖中的 Service A、Service B 和 Service T 是微服務拆分后的三個 Service,其中 Service T 是被測試對象,進一步假定 Service T 的消費者(也就是使用者)一共有兩個,分別是 Service A 和 Service B。

 
Service A、Service B 和 Service T 的關系.png

按照傳統的 API 測試策略,當我們需要測試 Service T 時,需要找到所有可能的參數組合依次對 Service T 進行調用,同時結合 Service T 的代碼覆蓋率進一步補充遺漏的測試用例。
但是這樣的話測試用例的數量會非常多,那我們就需要思考,如何既能保證 Service T 的質量,又不需要覆蓋全部可能的測試用例。

仔細想一下,會發現 Service T 的使用者是確定的,只有 Service A 和 Service B,如果可以把 Service A 和 Service B 對 Service T 所有可能的調用方式都測試到,那么就一定可以保證 Service T 的質量。即使存在某些 Service T 的其他調用方式有出錯的可能性,那也不會影響整個系統的功能,因為這個系統中並沒有其他 Service 會以這種可能出錯的方式來調用 Service T。

從本質上來講,這樣的測試用例集合其實就是,Service T 可以對外提供的服務的契約,所以我們把這個測試用例的集合稱為“基於消費者契約的 API 測試”。

那么接下來,我們要解決的問題就是:如何才能找到 Service A 和 Service B 對 Service T 的所有可能調用了。其實這也很簡單,在邏輯結構上,我們只要在 Service T 前放置一個代理,所有進出 Service T 的 Request 和 Response 都會經過這個代理,並被記錄成 JSON 文件,也就構成了 Service T 的契約。

 
收集消費者契約的邏輯原理.png

在實際項目中,我們不可能在每個 Service 前去放置這樣一個代理。但是,微服務架構中往往會存在一個叫作 API Gateway 的組件,用於記錄所有 API 之間相互調用關系的日志,我們可以通過解析 API Gateway 的日志分析得到每個 Service 的契約。

補充知識:API Gateway 一般是作為整個微服務的入口,做一些權限校驗,路由功能,並不是每個服務間都存在的,只有面向客戶端的服務才會有這一層。服務間的內部調用不走API Gateway 。

微服務測試的依賴解耦和 Mock Service
實現 Mock Service 的關鍵,就是要能夠模擬被替代 Service 的 Request 和 Response。

此時我們已經拿到了契約,契約的本質就是 Request 和 Response 的組合,具體的表現形式往往是 JSON 文件,此時我們就可以用該契約的 JSON 文件作為 Mock Service 的依據,也就是在收到什么 Request 的時候應該回復什么 Response。

下圖 解釋了這一關系,當用 Service X 的契約啟動 Mock Service X 后,原本真實的 Service X 將被 Mock Service X 替代,也就解耦了服務之間的依賴

 
基於 Mock Service 解決 API 之間的調用依賴.png


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM