分布式系統(tǒng)測(cè)試
單元測(cè)試
分布式系統(tǒng)的開發(fā)工作通常會(huì)被劃分成多個(gè)模塊,由不同的開發(fā)人員分別編寫程序,所以代碼的單元測(cè)試工作通常是針對(duì)單個(gè)模塊進(jìn)行的。如果模塊是獨(dú)立的,并 且功能集足夠小,單元測(cè)試是很容易做的,構(gòu)造一組case,盡量覆蓋所有的分支基本上就OK。但實(shí)際上分布式系統(tǒng)里很少有完全獨(dú)立的模塊,大部分的模塊都 會(huì)跟其他的模塊有依賴關(guān)系或是網(wǎng)絡(luò)通信等。
對(duì)于有依賴的模塊的單元測(cè)試,理想情況下,依賴的模塊都已經(jīng)準(zhǔn)備好,并且被測(cè)試過沒有問題 (這個(gè)實(shí)際上是做不到的,而且模塊間有時(shí)還會(huì)存在相互依賴的情況),這種理想情況會(huì)嚴(yán)重影響開發(fā)效率,使得有依賴的模塊就只能串行開發(fā)測(cè)試。另外,如果依 賴的模塊在安裝、部署上需要花費(fèi)很長(zhǎng)的時(shí)間(比如是一個(gè)配置比較麻煩的server),那么每次單元測(cè)試都需要把server部署起來(lái),測(cè)試成本是很高的。
實(shí)際單元測(cè)試的過程中,我們經(jīng)常會(huì)把依賴其他模塊的地方用簡(jiǎn)單的代碼代替,也就是做mock。最直觀的mock方式就是通過宏來(lái)控制,即如果是以 DEBUG模式運(yùn)行,執(zhí)行某段簡(jiǎn)單的代碼(mock),如果非DEBUG模式運(yùn)行,則執(zhí)行實(shí)際的代碼邏輯。比如通過下面一段代碼把“從網(wǎng)絡(luò)上獲取數(shù)據(jù)”在 DEBUG模式運(yùn)行時(shí)替換為“從本地內(nèi)存獲取數(shù)據(jù)”,那么在執(zhí)行單元測(cè)試時(shí),我們就不需要依賴網(wǎng)絡(luò)的對(duì)端來(lái)提供數(shù)據(jù),從而方便的測(cè)試代碼邏輯。而實(shí)際 fetch_data_from_network()的測(cè)試可延遲到功能測(cè)試階段。
#ifndef DEBUG_MODE fetch_data_from_network(); #else fetch_data_from_local_memory(); #fi |
使用宏來(lái)控制有時(shí)會(huì)使得代碼讀起來(lái)很混亂,如果是使用C++開發(fā)(或其他面向?qū)ο缶幊陶Z(yǔ)言),更好的方式是借助多態(tài)的性質(zhì)來(lái)做mock,如下面一段代 碼,DataManager是一個(gè)負(fù)責(zé)管理數(shù)據(jù)的類,它需要從網(wǎng)絡(luò)上其他的服務(wù)里獲取數(shù)據(jù),MockDataManager是一個(gè)繼承自 DataManager的類,它從本地內(nèi)存獲取數(shù)據(jù),在測(cè)試時(shí),我們可以將DataManager的實(shí)例換成MockDataManager的實(shí)例來(lái)運(yùn)行 (必須是指針或是引用),這樣思路跟前面的思路其實(shí)是一樣的,只不過借助多態(tài),更清晰明了,需要做的事情更少。google test和google mock是開源的測(cè)試、以及mock框架,使用他們會(huì)使你的測(cè)試工作更簡(jiǎn)單,更有趣。
class DataManager { class MockDataManager : public DataManager { |
測(cè)試久了之后,你會(huì)發(fā)現(xiàn)測(cè)試的工作量往往跟代碼結(jié)構(gòu)的設(shè)計(jì)有很大的關(guān)系,如果代碼結(jié)構(gòu)本身毫無(wú)章法,再加進(jìn)去一堆為單元測(cè)試而寫的代碼邏輯,只會(huì)令代碼 看起來(lái)更加糟糕;如果設(shè)計(jì)之初就考慮測(cè)試需求,盡量把業(yè)務(wù)與邏輯層次分開降低模塊間依賴性,把可能需要mock測(cè)試的地方設(shè)計(jì)為虛基類等,在做測(cè)試的時(shí)候 需要做的工作就會(huì)很少,而且測(cè)試新增代碼不會(huì)打亂現(xiàn)在的代碼邏輯結(jié)構(gòu)。
posted on 2013-05-20 10:44 順其自然EVO 閱讀(213) 評(píng)論(0) 編輯 收藏