自動化測試基礎設施(一)——為功能測試構建通用mock server系統
那么在功能測試(這里提到的功能測試指的是用戶級測試)這個層次,是否有必要使用mock呢?如果有必要又將如何構建呢?或者說是否有可能像單元測試中那樣構建一個通用的mock server系統呢?本文將根據我的實踐經歷,向大家介紹一個通用mock server系統的主要組成部分以及設計思路。
Why
現今的業務系統很少孤立存在,它們或多或少需要使用兄弟團隊或是其他公司提供的服務,這為我們的聯調和測試造成了麻煩。對于這種情況,我們常見的解決方 案是搭建一個臨時的server,模擬那些服務,提供數據進行聯調和測試。這就是mock server的雛形。一般來講,搭建這種mock server系統比較簡單,不過它的功能也比較簡單,而且往往需要針對不同的接口重復開發。那有沒有可能像單元測試中使用的mock框架那樣構建一個通用 的mock server系統呢?
How
觀察單元測試中的mock框架,我們會發現一般使用mock的流程是:
init mock //創建mock對象 config mock //設置mock期望 setup mock //將mock對象設置給被測對象 call //調用被測接口,被測接口里的代碼會調用mock對象 verify //驗證 拿mockito舉例: User expected = new User(“admin”, “12345”); //init UserDAO dao = mock(UserDAO.class); //config when(dao.findByName(“admin”)).thenReturn(expected); //setup UserService service = new UserService(dao); //call User actual = service.login(“admin”, “12345”); //verify or assert |
借鑒這種做法,我么就可以構建一個簡單的mock server系統,接下來的內容中,我們會在這個mock server的基礎上演化出比較完善的版本。
版本1(簡單的模擬值)
假設我們需要mock的是HTTP接口。我們的mock server提供一個配置接口(對應著上面的config mock步驟),測試運行之前調用配置接口將需要mock的HTTP接口URL以及需要返回的值傳遞過去,mock server內部建立url 到返回值的關聯(這里就類似存在一個哈希表一樣)。Mock server還提供另外一個接口供被測系統調用。這是一個通用的接口,所有原先指向真實服務的地址全部被指向到該接口(可以通過修改配置或修改系統 hosts文件)。當該接口被調用時會尋找剛才建立的url 到返回值的關聯,并將mock的值返回。這樣一個非常簡單的mock server就構建出來了,對于一些簡單的聯調場景基本夠用。這個時候我們的mock server的原理圖如下面所示:
版本2(提供調用參數的查詢)
有了第一版的mock server,對一些只需要模擬值的場景是夠用了。但是,mock的作用僅限于此么?想想單元測試中的mock。在單元測試中mock框架除了能夠為被測 系統構建輸入值外,還能捕獲到被測程序傳出的值,然后對這些值進行校驗。舉一個實際的例子:在我們的系統中經常需要向用戶發送短信,為了對發送的短信功能 以及短信內容進行驗證,在沒有mock之前我們可能真的需要向真實手機發 送短信,然后驗證。這不僅降低了測試效率,也增加了不少不可控因素。為此我給mock server添加第三個接口:query接口。在被測系統調用mock接口時,mock會記錄下被測系統傳遞給mock接口的參數值,然后測試中可以調用 query接口查詢到記錄的值,在測試中可以對其斷言,而且這里記錄下的調用記錄還可以作為日志提供出來,提高系統的診斷能力。這樣我們的mock server的結構就變成:
版本3(可以根據參數模擬)
現在我們的mock server已經可以提供類似verify的功能了,但實際上它還不能算一個真正的mock。它也不能處理哪怕稍微復雜一點的情況。在實際中,我們經常需 要針對不同的參數返回不同的值。舉個簡單的例子:我們mock一個支付接口,對于訂單號123我們期望支付成功,對于訂單234期望支付失敗。這就引入了 我的mock server的兩個核心組件:extractor和matcher。Extractor組件主要用于從調用的參數上提取出參數值,然后轉換成 key/value的格式提供給后續的環節使用;因為請求的參數格式多種多樣(json,xml等),extractor 為此提供了統一的接口。
Matcher組件的作用是在拿到extractor傳遞過來的key/value值后利用一些匹配器匹配到具體設置的期望上,所有匹配到的調用會返回 對應的值。也就是說mock server內部不再是簡單的映射了。后面再介紹DSL部分的時候會介紹matcher使用的語法。這樣我們的mock server結構就演化成下圖:
版本4(提供多種協議的支持)
估計有人在抱怨,說了這么多這個mock server還只能mock HTTP接口啊,我們的系統中存在HTTP接口,RPC接口,SMTP接口等等。這是mock server中協議組件的職責。協議組件是mock server的入口,它提供多種協議的服務,并且解析出協議包數據,然后將數據交給extractor組件;除此之外,協議組件在收到上層的返回值后,會 按照協議的格式返回給被測系統 。利用一些開源的類庫,我們可以很容易對一些通用協議提供支持,但對一些私有的二進制協議如果沒有現成的庫支持,要重新開發成本很大,不過我們可以從客戶 端來解決這個問題,這在后續的文章中會有介紹。
版本5(模擬行為)
基本上一個功能還算完善的mock server成型了。但這就夠了么?對于要模擬各種場景的測試還遠遠不夠。我們很多接口有回調的功能,我們通常還需要模擬接口超時的情況,而對于一些支付 相關的接口經常需要對參數進行加密解密,而且這些情況都需要是可配置的。有沒有發現,前面我們介紹的所有實際上都是mock值。也就是我們設置一些值,然 后調用的時候將值返回。但是很多時候我們不僅需要mock值,更要mock行為。這樣我們有了mock server中最核心的組件:命令執行引擎(好牛的名字,其實就那樣)。在設置mock的時候我們不再是設置一個值,而是設置一個預定義命令組合成的流水 線(即按照類似下面xml的配置一步一步執行,并且可以將上一步的執行結果傳遞給下一步):
<delay>1000</delay> <callback url=http://localhost/callback.do>{“ret”:”true”}</callback> <return>{“ret”:”true”}</return> |
上面的流水線被命令執行引擎解析執行后就是按順序執行對應的DelayCommand, CallbackCommand以及ReturnCommand命令了,具體命令就不介紹了。采取這種方式給我們mock server帶來了很大的靈活性:只需要簡單的擴展一個子命令,就可以擴充mock server的行為。比如mock某網關接口時需要使用MD5加密,只需要擴展一個MD5Command(下面代碼中的$result表示前一步驟 <md 5 />加密后的結果):
<md5 /> <return>$result</return> |
DSL
現在我們的mock不僅可以mock值了,對于各種行為的模擬也得心應手。但是要使用方便,還要提供便于使用的接口。Mock server提供兩類接口:針對自動化測試的DSL,以及針對手工測試使用的管理界面。這里主要介紹這種DSL(因為我們的測試用例是使用xml編寫,轉 換成編程語言也很容易):
<mock service=”http:/test.json” matcher=”hasKey($param.orderNo)”> <delay>1000</delay> <md5 /> <return>$result</result> </mock> |
service是對被mock的服務的描述,比如對于SMTP,我們可以這樣定義: service="smtp:9000"。這個表示在9000端口上監聽smtp協議。而matcher即前面介紹的matcher組件所使用的各種匹配 器,用于匹配被測系統調用mock server時傳遞的數據。比如上面的例子表示的就是如果被測系統調用http接口/ticket.jsp,并且參數里包含orderNo則延遲1秒鐘, 然后返回一個json值 。
總結
前面幾節介紹了一個比較完善的通用mock server從簡到繁演化的設計思路,希望可以為想要構建類似設施的讀者提供一個參照。
這個mock系統包含兩個主要部分:mock admin和mock server。Mock admin是管理界面,主要提供監控(可以在界面上實時看到被測系統與mock server交互)以及手工測試時的配置界面。 Mock server即前面介紹的主體,其架構如上圖所示。Mock server包含幾個核心組件:協議、extractor、matcher、命令執行引擎、存儲(即mock server中使用的各種數據的存儲)。Mock server提供三類接口:配置、被mock接口(各種服務,通過協議組件提供)、查詢。
原文:http://www.infoq.com/cn/articles/auto-test-mock-server
posted on 2013-05-27 10:14 順其自然EVO 閱讀(361) 評論(0) 編輯 收藏 所屬分類: selenium and watir webdrivers 自動化測試學習