mock測試方法及實踐改進
此文已由作者翟曜授權網易雲社群釋出。
歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。
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大概的工作原理
【推薦】 如何實現最佳的跨平臺遊戲體驗呢?