文本轉載自個人博客:littleliang.xyz/2019/09/18/…正則表達式
在敏捷開發的過程當中,客戶端與後臺開發一般是同時進行的,常常會出現客戶端須要等待後臺開發完成才能驗證客戶端邏輯的狀況。等待聯調每每會成爲阻塞項目進展的瓶頸。Cgimock工具的做用就是解除客戶端對後臺的依賴,解決數據源的問題,提高客戶端開發和調試的效率。編程
以往的的產品決策流程須要等待後臺開發完成,上到測試服務器上,才能讓產品經理體驗。有了cgimock工具,能夠用模擬數據代替後臺數據。快速輸出產品原型,下降試錯的時間成本。服務器
CgiMock工具能夠幫助開發者在不侵入代碼的狀況下,構造模擬數據,模擬網絡回包。它的工做模式分爲兩種:微信
第一種是在Cgi請求階段攔截請求,返回預設好的模擬數據給業務層。適用於後臺尚未數據返回的全新業務場景。網絡
第二種模式是,在請求階段不攔截,等到後臺返回回包後,將模擬數據與後臺回包進行合併,再返回給業務層。通常應用於對已有業務的變動。架構
業界對於CgiMock的實現方式也分爲兩類,一類是搭建MockServer,在服務器端攔截請求。第二種是終端CgiMock,在客戶端上攔截請求。MockServer方案的優點是與平臺無關,自然支持跨平臺。但該方案有如下的缺點:首先,若是要支持模式二須要將MockServer與後臺服務器對接,有額外的開發工做。其次,MockServer須要解析客戶端的請求包,因此須要支持客戶端使用的數據交換格式,通用性很差。最後,搭建和維護MockServer也有必定的成本。app
而終端CgiMock因爲是在客戶端上攔截請求,因此適配模式2很是容易,也不須要考慮客戶端的數據交換格式,通用性更好。可是若是想要實現跨平臺,須要在不一樣平臺上都實現Mock組件。框架
權衡了二者的優缺點,我認爲終端CgiMock方案的通用性與靈活性更好,使用者無需作太多額外的工做。因此在技術選型上,我選擇了終端CgiMock的解決方案。dom
隨後,我調研了一些業界關注度較高的終端CgiMock開源項目,包括阿里的OHHttpstubs以及廣研的GYHttpMock。得出瞭如下比較結果,OHHttpstubs做爲一款業界使用最多的終端cgimock開源工具,實際上只是知足了模擬網絡回包的基本需求。編程語言
首先,它的mock代碼是用原生語言寫的,不支持跨平臺。第二,不支持後臺數據與模擬數據合併。第三,不支持Mock用例的組織,只可以以Cgi爲單位的mock。第四,不支持熱更新。最後,它只支持基於NSURLSesion網絡庫,像是微信這種使用自研網絡組件的應用沒法使用。GYHttpMock則在它的基礎上增長了模式二的支持。以及支持從JSON文件中讀取回包數據和正則表達式匹配。
比較事後,現有的開源工具並不知足個人需求。因此我決定設計一款功能更豐富,通用性與易用性更好,能夠給項目中不一樣角色使用的CgiMock工具。我命名它爲WCCgiMock。
我遇到的第一個問題,就是須要選擇一門合適的語言來編寫CgiMock代碼。爲此,我定了三個須要符合的要求:
結合這三點的要求,我選擇了JavaScript做爲Mock代碼的編寫語言。JavaScript除了知足上述要求,在iOS和Android平臺上,都有很是成熟的JSBinding技術,能讓JS代碼與原生代碼相互通信。
引入一門新的語言,確定會帶來必定的學習成本,關鍵是如何經過設計來最大程度地下降這個成本,WCCgiMock的目標是想作到讓非開發人員,像是測試或者產品也能輕鬆上手。
爲此,我設計了適用於JavaScript上的內部DSL語句來描述提供的功能。內部DSL,指的是利用某種編程語言的特性,將針對特定目的的處理用高級、簡潔的方式進行描述。它的優勢在於能夠經過鏈式調用串聯各個語句,接近天然語言,符合人的思惟習慣。並且,DSL語句將處理過程高度抽象,使用者能夠專一於目標,不須要理解過程的實現,這可以下降編寫Mock代碼的學習成本。
我將mock過程的步驟及參數配置,抽象爲了若干個DSL語句。
mockRequest語句,用於聲明一個CgiMock。聲明後,每當這個cgi發起請求,都會根據隨後設置的參數返回模擬數據。withRequest語句用於修改請求參數。andreturn與withresponse語錄分別是設置回包的返回碼與回包數據內容。updateFromSvr語句,設置是否與後臺回包合併。
除了mockRequest語句外,其餘語句都不是必須調用,使用者能夠根據目的來自由組合語句
這裏展現一個Mock腳本的例子:
能夠看到,這種基於方法鏈的流暢風格代碼,接口定義簡潔,閱讀起來與天然語言類似,很是容易理解。
除了使用DSL語句,WCCgiMock相比於其餘開源工具還提供了響應式數據的能力,基於這個能力,Mock腳本能夠模擬後臺邏輯,根據請求內容來返回不一樣業務分支的模擬回包。
使用者可在腳本中定義不一樣分支的模擬回包,並實現serverLogic方法。當這個Cgi請求時,Native層會經過jsbridge回調這個方法,並傳入請求的數據。ServerLogic可根據請求內容返回不一樣的回包給Native層。
相比於靜態化的數據返回,動態化的響應式數據不須要每驗證一個分支就要切換或是修改數據,調試起來更高效。
響應式數據,還能起到質量保障的做用。基於這個能力,後臺開發可根據產品用例生成帶有模擬後臺邏輯的Mock用例給到客戶端開發與測試工程師,客戶端開發可根據模擬後臺邏輯處理全部的業務分支,避免因爲後臺邏輯的不透明而致使某個分支沒有處理的狀況,減小客戶端自身的邏輯異常。
對於測試來講,很大的一個痛點是,測試時須要詢問需求涉及哪些cgi,協議改動了哪裏,後臺邏輯是什麼。這些以往都須要與開發進行溝通才能獲知。而如今根據Mock腳本就能瞭解到這些信息,快速地輸出測試用例,節省了雙方的溝通成本。測試工程師還可在用例上添加構造各類數據,特別是一些邊界場景數據和異常數據。提高客戶端對後臺數據的容錯能力。
產品也能夠在後臺未完成的狀況下體驗完整的產品流程,包括各個業務分支及錯誤處理。
講一個真實的案例,年初龍哥提出春節要作拜年紅包,當時時間很是緊迫,須要在很短期內完成demo讓老闆體驗,可是後臺評估須要一週的開發時間。響應式數據的能力就起到了做用。利用響應式數據,我只用了兩天時間就輸出了Demo,讓老闆在沒有感知到是模擬數據的情下體驗了整個產品的流程,敲定了最終的方案,產品根據方案快速地調整了方向,使項目最終得以順利上線。這個例子體現了響應式數據對加速產品決策起到了做用。
WCCgiMock另外一個核心能力是支持組織用例。業界上的工具是都是以單個Cgi爲單位進行mock。但實際狀況是,一個完整的業務流程一般是由多個模塊,多個Cgi構成的。
舉個例子,綁定銀行卡做爲一個通用的業務模塊,常常被其餘業務所使用,咱們能夠將綁卡流程單獨寫成一個Mock用例,其餘業務使用時,直接引用便可。
用例的組織能夠用一棵樹來描述,Mock腳本是葉子節點,由DSL語句構成。UseCase是非葉子節點,由require語句構成,用於聲明UseCase由哪些Mock腳本和其餘UseCase構成。require語句會將目標腳本加載到JS環境中,並執行腳本中的DSL語句。
相比於以cgi爲單位的mock,組織用例具備一下的優點
在iOS模擬器和Android平臺上,因爲沒有嚴格的沙盒機制,實現熱更新比較簡單。這裏重點說一下iOS真機環境下的熱更新解決方案。iOS真機環境因爲沙盒機制的限制,沒法將Mock腳本直接寫入app沙盒中。我在組內的HotLoader工具基礎上作了改動,實現了iOS真機環境下的熱更新。
HotLoader工具基於usbmuxd服務和watchdog文件監控。usbmuxd服務能夠將USB通訊抽象爲TCP通訊。至關於app是Server端,mac設備是Client端。兩端經過usb端口來傳送數據。watchdog的做用是監聽Mock用例文件的修改事件,當用例文件被修改時,kernel就會向watchdog發出通知,這時HotLoader會將Mock用例打包, 經過usb端口將用例傳輸到App端上,通知CgimockMgr重載腳本。
使用HotLoader,開發者不須要去作額外的操做,每當修改、保存用例後,工具會將修改後的Mock用例自動打包,發送到設備上,並重載生效。調試過程很是方便。
介紹完核心能力,接下來闡釋一下WCCgiMock是如何實現JS代碼與原生代碼通訊。
JS代碼與原生代碼通訊的實現基於JSBinding技術。JSBinding引擎做爲橋接層,在JavaScript代碼與原生代碼之間創建一座橋樑,使JS對象與原生對象相關聯,雙方能夠互相調用。
該三層結構,對應於WCCgiMock的實現以下圖所示
JS層中CgiMock.js文件定義了提供給Mock腳本調用的接口方法。包括聲明方法mockRequest,用例組織方法require,日誌打印方法。此外我還利用了JavaScript的原型鏈特性,爲原型對象Object提供了一些工具函數,讓使用者能夠更方便地編寫serverlogic代碼。當WCCgiMock初始化時,會將CgiMock.js載入JS運行環境中
JSBinding層中,我在JSContext上註冊了相應的橋接方法,提供給JS層調用。橋接方法會將傳入的js數據類型轉爲原生數據類型,再去調用Native層中的具體實現。
在Native層中,CgiMockDSL類定義了全部DSL語句,並經過JSExport協議註冊到JSContxt中。全部DSL方法都會返回CgiMockDSL類的實例對象,經過JSBinding引擎轉換爲JSObject,返回到JS環境中,因此在JS環境中就可使用這個JSObject調用下一個DSL語句,從而實現鏈式調用。
這就是整個通信過程的基本原理
總結一下WCCgiMock的總體架構,
總體架構主要分爲7個模塊
CgiMockMgr負責組織各個模塊,並將模擬數據返回給網絡層
若是想要擴展功能的話,只須要在JS層去作擴展就能夠了。好比隨機數據生成這個能力,之前是沒有的。經過在js層進行擴展,只須要寫一套代碼就能夠在多個平臺上都實現這個功能。
目前
WCCgiMock做爲一套敏捷開發工具,可以起到提高開發效率、加速產品決策、保障客戶端質量的做用,目前已經實現了iOS/Mac、Android端的客戶端組件和配套的可視化工具鏈。WCCgiMock已在微信iOS客戶端團隊,測試組推廣使用,支付團隊推廣使用,累積的Mock用例已達一百多個。
將來
WCCgiMock是否會開源?答案是確定的。目前正在整理代碼,很快會向公司提出開源申請,相信WCCgiMock很快就會與你們見面。