此文已由作者翟曜授權網易雲社區發布。
歡迎訪問網易雲社區,了解更多網易技術產品運營經驗。
mock測試常見的定義為:在測試過程中,對於某些不易構造或不易獲取的對象,通過創建虛擬對象的方式來模擬測試的測試方法。
提到mock測試工具,java領域內可能首先想到的是Jmock、EasyMock、JMockit等。通常在單元測試中,由於對象、方法不是獨立的,測試代碼難以構造,所以業界提出了Mock Object技術來孤立被測試的對象。以上幾種Mock 框架都限於一個Mock概念:即Mock Object 是用來代替與代碼協作的對象的對象。和這幾種框架一樣,其他的 mock 框架也基本都局限於單元測試范疇,而在集成測試功能測試階段還沒有相應成熟的框架進行支持。所以本文提到的mock測試,更確切來說,是在功能測試階段解決如何與外部系統間的數據交互。
文章結合本人所在的項目【秀品】來做相關介紹。大多用戶直接接觸到的只是秀品商城,但實際整個秀品業務系統的運轉比較復雜,其中便涉及到和多個外部系統的對接及數據交互,比如倉儲和物流都會和EMS、順豐等有數據交互。而最近秀品開始涉及跨境業務,相應和電子口岸、境外的物流商等又會有數據交互。
當然,跟外部系統對接時系統間的聯調測試必不可少,有些外部系統提供測試環境,有些甚至不提供。即便是提供測試環境的外部系統,一般也僅在開發聯調階段配合提供聯調測試對接服務,一旦聯調測試結束,也不再繼續提供測試服務。那么,當這些外部系統的聯調測試環境不可用時,我們就需模擬這些外部系統來和秀品系統進行數據交互,以便支持秀品完整業務測試流程的正常進行。針對這類mock測試需求,秀品QA做了幾種實踐,也是在實踐中總結再改進的過程。
秀品系統采用的通信協議主要有:dubbo協議和http協議。和外部系統對接都是采用http協議,所以目前只需模擬外部系統對秀品系統的http請求回調功能。
以秀品和EMS(倉儲物流商)的WMS(倉庫管理系統)交互為例,EMS會提供一份標准對外接口文檔給秀品。不同業務接口的調用形式和接口參數基本是一致的,僅通過參數值傳遞與業務相關的數據。約定如下圖所示:
以其中一個WMS回傳消息接口為例:【入庫單收貨確認回傳接口】,其處理業務說明:WMS系統在入庫單完成入庫(上架)后,將對應入庫信息回傳給外部系統(即秀品)。EMS提供的文檔說明如下圖:
結合秀品系統實現,EMS的回調最終只需拼接成這樣一個請求:
秀品某測試機Ip+http端口號+調用路徑+servicename+appkey+content(xml格式)
其中:Ip+端口+調用路徑+appkey 與測試環境配置相關,基本不隨業務變化。
servicename+content(xml格式)和業務有關,頻繁變化。
針對該【入庫單收貨確認回傳接口】,則只需拼接並執行這樣一個請求:
http://host:port/oms/wms/ems?service=WmsStockInConfirm&appkey=xxxxxx&content=< RequestReceiveInfo> xxxxxxxx</RequestReceiveInfo>
說明:content為上圖中xml格式的數據集。
如何處理這類mock測試?
WAY1:尋找能發送http請求(get\post)的測試工具,例如fiddler、postman。
fiddler大家都比較熟悉,主要介紹下項目中使用的postman。Postman 是Chrome 擴展,提供功能強大的 Web API & HTTP 請求調試。它能夠發送任何類型的HTTP 請求 (GET, HEAD, POST, PUT..),附帶任何數量的參數+ headers。其具備兩個主要優點:
1.能夠保留歷史請求,這樣我們就可以很容易地重新發送請求;
2.有一個“集合(collection)”功能,用於存儲所有請求相同的API/域。
使用效果如圖:
Postman其實已足以滿足大部分同類測試需求,且使用成本不高,不需額外編寫測試代碼。但結合我們項目特點,這些mock會影響每一次訂單流程扭轉的測試,使用頻率非常高,且存在許多需要mock的回調接口。所以,針對這些影響可得出以下可改進點:
1.數據主要集中在xml中,每次執行需根據不同測試數據更改xml,改起來費時費力且易出錯。
2.雖有“集合”功能,但一個人的測試集也不便於及時共享給其他同學。
3.操作界面雖有b格,但過於簡陋,真心不便。
綜合postman的優缺點,不如嘗試把測試集固化到java代碼里,因此開始了嘗試WAY2:利用java代碼,基於httpclient發送請求。類似於http接口測試,測試集代碼如下圖:
說明:
分別構造出請求url,xmlinfo及所需各參數后,執行請求即可。針對xml的處理,每次執行只需參照代碼注釋更改相應框內的屬性值即可,減少編輯時間和出錯概率,且一人寫的代碼其他同學都可以共用,總體還是提高了測試效率,基本滿足了測試需求,但仍存有可改進點:
1.執行時要基於IDE,需要更改xml文件中相應屬性值,同時必須具備代碼運行環境。
2.沒有可視化操作界面,存在使用門檻,操作不夠方便。
如果傳參更為簡單,使用者無需接觸測試代碼,不用基於本地運行環境且能夠可視化執行,這樣可進一步提升測試效率,於是開始了嘗試WAY3:模板語言在mock測試中的應用,並結合jenkisn實現用戶界面。最便捷的方式首先想到了結合jenkins,通過運行jekins job,只需在可視化的界面里傳入參數值,便可“一鍵執行”成功模擬出接口的回調,很好地解決待改進的問題。
針對該解決方案:
首先,測試代碼需上傳服務器,需解決服務器上構建打包的規范問題,以便可以通過命令行傳入參數調用到不同測試類及模板文件。
其次,針對xml文件作為請求參數,考慮引入FreeMarker模板引擎,基於模板生成xml文件輸出。提取出xml中在實際測試場景中需頻繁更新的屬性,重新定義成一個Java do類,向匹配的ftl文件傳值。從而整體簡化測試代碼的繁鎖度。
另外,從工具使用角度考慮,傳參過多,也會較繁鎖,所以考慮將輸入的參數合並為長字符串,傳遞到程序后再做拆分處理。
總之,在設計代碼結構及編寫程序時,秉承着一個原則:盡可能通用化。
結合最終需拼接並執行的請求形式:
Ip+端口+調用路徑+servicename+appkey+content(xml);
其中Ip+端口+調用路徑+appkey 與測試環境配置相關,基本不變;
servicename+content(xml)和業務有關,頻繁變化。
做了如下改進:
1.將請求url中環境配置相關的共通部分抽取,定義為CommonURLDo,以便可以靈活運行在不同的測試環境。
2.將不同業務接口(servicename)對應的xml定義為不同的ftl模板文件。並將模板需頻繁變化的變量提取,定義成業務DO類,建立DO和ftl的映射,通過DO向ftl傳參。
3.為測試類更通用,將ServiceName參數化,通過傳入的ServiceName,渲染出相應的ftl模板文件。一個測試主類便可支持所有同類的需求。
4.最后,針對一個業務場景,配置相應jenkins job,傳入三部分必需的參數:【測試類名】+【與環境配置相關的通用信息】+【xml文件需頻繁變化的屬性值】,執行job,便可完成一次回調模擬。
如圖,代碼結構組織及大體實現如下:
首先,定義ftl模板文件及相應DO。
其次,執行測試主類main方法,參數依賴於jenkins job執行傳入,執行主要分為3個steps:
其中,step2中根據不同servicename調用不同業務處理類,實現如下:
最終,jenkins job的使用者界面如下:
借助於jenkins的用戶界面,成功實現了“一鍵執行”。
那么,來運行一個mock測試試試吧~
至此,一個完整的mock測試場景已成功完成。
在自己編寫和使用工具過程中,也會不斷總結出一些待優化點,根據項目后續實際需要再做擴展。當然,現在這種方式仍有其局限性:
1.如果可以更通用,實現通用的mock server,client端使用時不需添加測試代碼且有操作頁面,只需在頁面上進行簡單配置便可成功執行測試;
2.能夠以產品/項目維度對場景用例進行維護,共享並存儲一份測試case,維護管理更便捷;
3.能夠提供對多種協議的支持,例如http、dubbo、hessian等;
4.對自動化測試和性能測試的支持,提供自動化的API調用,甚至可以對一些壓力測試場景提供支持。
如果可以實現一個通用mock測試平台,整體上將更利於測試效率的提升。
更多網易技術、產品、運營經驗分享請點擊。
相關文章:
【推薦】 私有雲爆發,未來增長空間巨大
【推薦】 kubernetes大概的工作原理
【推薦】 如何實現最佳的跨平台游戲體驗呢?