999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

基于模擬對(duì)象Mock Object的單元測(cè)試研究

2008-01-01 00:00:00
電腦知識(shí)與技術(shù) 2008年5期

摘要:在軟件測(cè)試中,單元測(cè)試不僅能夠優(yōu)化軟件系統(tǒng)設(shè)計(jì),還大大簡(jiǎn)化了功能測(cè)試的測(cè)試量。但是在一些情況下進(jìn)行單元測(cè)試比較困難,本文引入了模擬對(duì)象Mock Object的概念,利用Mock Object進(jìn)行單位測(cè)試,解決了傳統(tǒng)單元測(cè)試中存在的一些問題。

關(guān)鍵詞:軟件測(cè)試;單元測(cè)試;模擬對(duì)象

中圖分類號(hào):TP311文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2008)05-00ppp-0c

1 引言

隨著極限編程在實(shí)際軟件開發(fā)項(xiàng)目中的推廣,越來越多的項(xiàng)目開始采用測(cè)試驅(qū)動(dòng)開發(fā)作為主要的軟件開發(fā)方法。單元測(cè)試不僅優(yōu)化了軟件系統(tǒng)設(shè)計(jì),還大大簡(jiǎn)化了功能測(cè)試的工作量[1]。但是另一方面.更多的項(xiàng)目在開始不久就發(fā)現(xiàn)在很多情況下針對(duì)一個(gè)類編寫單元測(cè)試比較困難.隨著項(xiàng)目的進(jìn)行,越來越多的代碼無法進(jìn)行單元測(cè)試.到最后整個(gè)項(xiàng)目無法繼續(xù)采用測(cè)試驅(qū)動(dòng)的方式進(jìn)行開發(fā)。因此,要將測(cè)試驅(qū)動(dòng)開發(fā)真正在整個(gè)項(xiàng)目里貫徹執(zhí)行,必須有一種方法能夠相對(duì)容易的解決這些問題。本文將首先討論了單元測(cè)試和無法或很難進(jìn)行單元測(cè)試的情況,然后引入Mock Object的概念,基于Mock Object實(shí)現(xiàn)單元測(cè)試。接下來討論在軟件開發(fā)過程中引入Mock Object對(duì)測(cè)試和設(shè)計(jì)的影響。最后簡(jiǎn)述了Mock Object的局限性。

2 單元測(cè)試

2.1 什么是單元測(cè)試

單元測(cè)試是對(duì)程序中的單個(gè)子程序或過程進(jìn)行測(cè)試的過程,也就是說,一開始并不是對(duì)整個(gè)程序進(jìn)行測(cè)試,而是將注意力集中在對(duì)構(gòu)成程序的較小模塊的測(cè)試上面[2]。單元測(cè)試從兩個(gè)角度進(jìn)行測(cè)試:一是測(cè)試數(shù)據(jù)都是針對(duì)程序的功能來設(shè)計(jì)的黑盒測(cè)試;二是針對(duì)程序的邏輯結(jié)構(gòu)來設(shè)計(jì)測(cè)試用例的白盒測(cè)試。

2.2 單元測(cè)試面對(duì)的難題

造成針對(duì)一個(gè)類難以進(jìn)行單元測(cè)試的主要原因是因?yàn)檫@個(gè)類依賴于一些其它的難以測(cè)試的資源。主要有這三類最主要的資源:數(shù)據(jù)庫,第三方組件和網(wǎng)絡(luò)硬件資源。下面我們將對(duì)這三大類難以測(cè)試的資源進(jìn)行分類討論。

2.2.1 數(shù)據(jù)庫

現(xiàn)在大部分的軟件項(xiàng)目都會(huì)采用數(shù)據(jù)庫作為數(shù)據(jù)存儲(chǔ)。常見的開發(fā)團(tuán)隊(duì)會(huì)在每個(gè)開發(fā)人員的機(jī)器上安裝一個(gè)本地的數(shù)據(jù)庫,每個(gè)人針對(duì)自己的數(shù)據(jù)庫進(jìn)行開發(fā)調(diào)試。這樣做的問題是:必須有一種方式同步數(shù)據(jù)庫的設(shè)計(jì)。如果有一個(gè)人修改了數(shù)據(jù)庫schema或者某個(gè)存儲(chǔ)過程,這個(gè)修改必須同步到所有開發(fā)者的本地?cái)?shù)據(jù)庫以及測(cè)試服務(wù)器上。采用敏捷軟件開發(fā)的很多項(xiàng)目組往往會(huì)浪費(fèi)大量的時(shí)間在數(shù)據(jù)庫設(shè)計(jì)同步上。更嚴(yán)重的是每周都會(huì)遇到由于數(shù)據(jù)庫設(shè)計(jì)不同步,修改沖突導(dǎo)致的問題導(dǎo)致整個(gè)項(xiàng)目的中心源碼庫在Auto Build時(shí)失敗。每個(gè)開發(fā)人員都有自己的測(cè)試數(shù)據(jù),除了上面提到的需要把這些測(cè)試數(shù)據(jù)同步到所有開發(fā)機(jī)器和測(cè)試服務(wù)器上外,還面臨更重大的問題。因?yàn)闇y(cè)試用例需要修改數(shù)據(jù)庫,因此還必須準(zhǔn)備一種機(jī)制能夠在每一個(gè)測(cè)試用例執(zhí)行結(jié)束后重新將所有的測(cè)試數(shù)據(jù)調(diào)入數(shù)據(jù)庫。采用最簡(jiǎn)單直接的方法就是在每個(gè)測(cè)試用例執(zhí)行前都將數(shù)據(jù)庫清空,然后再將測(cè)試數(shù)據(jù)調(diào)入,這樣會(huì)大大減慢單元測(cè)試的時(shí)間。單元測(cè)試時(shí)間越長(zhǎng),開發(fā)者就越不愿意執(zhí)行這些測(cè)試用例,單元測(cè)試所發(fā)揮的作用越小,這也是很多測(cè)試驅(qū)動(dòng)項(xiàng)目最終無法進(jìn)行到底的一個(gè)重要原因。另一個(gè)非常嚴(yán)重的問題是為了清理測(cè)試環(huán)境,在針對(duì)商業(yè)邏輯的測(cè)試用例中加入了大量的數(shù)據(jù)訪問層的代碼。采用這樣的方式強(qiáng)迫開發(fā)者在開發(fā)商業(yè)邏輯層的同時(shí)開發(fā)數(shù)據(jù)訪問層,并且嚴(yán)重降低了可讀性。

2.2.2 第三方組件或應(yīng)用服務(wù)器

數(shù)據(jù)庫是最常見的第三方服務(wù)器。除此以外在越來越多的項(xiàng)目中使用第三方的組件和應(yīng)用服務(wù)器。例如:客戶環(huán)境中的ERP系統(tǒng),全球定位系統(tǒng)(GPS)的Web Service接口,繪圖引擎等。對(duì)于這些第三方提供的內(nèi)容,造成難以編寫單元測(cè)試的最根本的原因有:一是系統(tǒng)不透明:對(duì)于大部分商業(yè)組件或者服務(wù)來說,一個(gè)很重要的內(nèi)容是良好的封裝。但這個(gè)特性帶來的問題是在外界無法對(duì)其內(nèi)部狀態(tài)進(jìn)行控制和訪問。往往經(jīng)過好幾個(gè)操作后才能在外部觀察到相應(yīng)的變化。二是環(huán)境配置困難。由于項(xiàng)目組成員計(jì)算機(jī)配置不同,加入項(xiàng)目的時(shí)間不同,在項(xiàng)目中負(fù)責(zé)的內(nèi)容不同導(dǎo)致無法為所有開發(fā)人員配置一個(gè)完全一致的環(huán)境。例如一個(gè)繪圖引擎的開發(fā)版的license是按照一個(gè)局域網(wǎng)內(nèi)部同時(shí)使用的人員個(gè)數(shù)收費(fèi)的,就不可能只為了能夠進(jìn)行完整的單元測(cè)試就為只編寫商業(yè)邏輯層的開發(fā)人員也安裝一套。

2.2.3 網(wǎng)絡(luò)資源和硬件資源

在稍大一些的項(xiàng)目中都或多或少的用到一些網(wǎng)絡(luò)資源。例如將文件部署到遠(yuǎn)程的webDAV服務(wù)器上同時(shí)很多項(xiàng)目還會(huì)用到一些硬件資源。常見的有打印機(jī)、指紋識(shí)別驗(yàn)證或者條形碼閱讀器等。這些資源有兩大特點(diǎn)導(dǎo)致很難針對(duì)與他們相關(guān)的類編寫測(cè)試用例。

一是資源訪問沖突。很多網(wǎng)絡(luò)資源對(duì)于并發(fā)訪問的響應(yīng)協(xié)調(diào)是通過鎖機(jī)制進(jìn)行的,在實(shí)際項(xiàng)目中常見的是一個(gè)開發(fā)人員在調(diào)試本地代碼時(shí)導(dǎo)致遠(yuǎn)端資源被鎖定導(dǎo)致其它開發(fā)者無法訪問這些資源。

二是環(huán)境可控因素。對(duì)于網(wǎng)絡(luò)資源和硬件資源相關(guān)代碼的測(cè)試與針對(duì)商業(yè)邏輯層代碼的測(cè)試最大的不同是環(huán)境的不確定性。訪問網(wǎng)絡(luò)資源有可能遇到的異常情況非常多,例如網(wǎng)絡(luò)忙造成訪問超時(shí),也有可能建立鏈接后數(shù)據(jù)傳輸失敗,還有可能數(shù)據(jù)傳輸完成后校驗(yàn)失敗。針對(duì)訪問這些資源的代碼進(jìn)行的測(cè)試必須能夠覆蓋到所有可能出現(xiàn)的每一種情況。如果沒有一個(gè)可控,并且是全自動(dòng)的環(huán)境輔助單元測(cè)試的話,這項(xiàng)任務(wù)基本上不可能完成。

3 模擬對(duì)象

3.1 什么是模擬對(duì)象

Mock這個(gè)單詞翻譯成中文大概的意思是假的,模擬的。如圖1所示:通過一個(gè)常見的對(duì)商業(yè)邏輯的測(cè)試描述了一個(gè)Mock Object。在圖中我們可以看出:測(cè)試代碼需要測(cè)試商業(yè)邏輯,而商業(yè)邏輯代碼需要通過IMyDataAccess接口訪問底層數(shù)據(jù)庫,這就是數(shù)據(jù)庫依賴問題。為了解決這個(gè)問題我們引入一個(gè)Mock Object,并將這個(gè)Mock Object而非真正的Data Access傳遞給商業(yè)邏輯代碼進(jìn)行測(cè)試。這里的Mock Object不需要實(shí)現(xiàn)任何邏輯只需要根據(jù)商業(yè)邏輯的需要返回適當(dāng)?shù)膬?nèi)容就可以了。

圖1 使用Mock Object對(duì)商業(yè)邏輯進(jìn)行測(cè)試

3.2 模擬對(duì)象實(shí)現(xiàn)單元測(cè)試應(yīng)用實(shí)例

現(xiàn)在我們寫好了類AccountService,具體如下:

public class AccountService {

private AccountManager accountManager;

public void setAccountManager(AccountManager manager) {

this.accountManager = manager;

}

public void transfer(String senderId, String beneficiaryId, long amount) {

Account sender = this.accountManager.findAccountForUser(senderId);

Account beneficiary =

this.accountManager.findAccountForUser(beneficiaryId);

sender.debit(amount);

beneficiary.credit(amount);

this.accountManager.updateAccount(sender);

this.accountManager.updateAccount(beneficiary);

}}

現(xiàn)在我們想測(cè)試transfer方法,它內(nèi)部調(diào)用的AccountManager的兩個(gè)方法。但是對(duì)于AccountManager來說,它只是個(gè)接口,如下:

public interface AccountManager {

Account findAccountForUser(String userId);

void updateAccount(Account account);

}

所以現(xiàn)在我們必須寫個(gè)MockAccountManager對(duì)象。而且里面的方法體都是非常簡(jiǎn)單的,就是假定它就返回某某值。

我們這里還有Account類。

public class Account {

private String accountId;

private long balance;

public Account(String accountId, long initialBalance) {

this.accountId = accountId;

this.balance = initialBalance;

}public void debit(long amount) {

this.balance -= amount;

}

public void credit(long amount) {

this.balance += amount;

}

public long getBalance() {

return this.balance;

}

public String getAccountId() {

return accountId;

}}

public class AccountService1Tests extends TestCase {

public void testTransfer(){

AccountService as = new AccountService();

MockAccountManager mockAccountManager=new MockAccountManager();

Account accountA = new Account(\"A\",3000);

Account accountB = new Account(\"B\",2000);

mockAccountManager.addAccount(accountA);

mockAccountManager.addAccount(accountB);

as.setAccountManager(mockAccountManager);

as.transfer(\"A\",\"B\",1005);

assertEquals(accountA.getBalance(),1995);

assertEquals(accountB.getBalance(),3005);

}}

這里我們?cè)诩俣ˋccountManager方法都工作正常的情況下,完成了對(duì)transfer方法的測(cè)試。

從以上代碼可以看出,采用Mock Object進(jìn)行的單元測(cè)試基本上可以分為下面幾步:

(1)基于一個(gè)接口定義Mock并實(shí)現(xiàn)這個(gè)接口的所有函數(shù)。

(2)創(chuàng)建Mock Object的一個(gè)對(duì)象

(3)設(shè)置對(duì)象內(nèi)部屬性

(4)告訴對(duì)象測(cè)試代碼希望看到的反應(yīng)

(5)進(jìn)行測(cè)試

(6)檢查Mock Object的確按照希望的順序進(jìn)行工作。

3.3 模擬對(duì)象的優(yōu)點(diǎn)

3.3.1 模擬對(duì)象作為測(cè)試手段的優(yōu)點(diǎn)

Mock Object最直接的優(yōu)點(diǎn)在于提供單元測(cè)試的質(zhì)量和覆蓋率:

(1)只要在測(cè)試中對(duì)期待發(fā)生的問題指定好執(zhí)行的順序引入Mock Object對(duì)象后的單元測(cè)試就是在一個(gè)完全可控的環(huán)境里進(jìn)行的。也就是說我們?cè)僖膊粫?huì)無法定位一個(gè)“時(shí)隱時(shí)現(xiàn)”的bug。相反我們可以非常迅速的將問題定位在一個(gè)類的內(nèi)部,而不是一個(gè)函數(shù)調(diào)用序列。

(2)于測(cè)試人員來說,最常見的問題是測(cè)試人員提交的bug無法在開發(fā)人員那里復(fù)現(xiàn)。有了Mock Object這個(gè)工具測(cè)試人員可以利用Mock Object明確的指定輸入和輸出編寫一個(gè)測(cè)試用例讓開發(fā)人員修復(fù)。

(3)超過8O% 的異常處理代碼沒有被充分測(cè)試過。主要原因是在沒有Mock Object之前很多情況是無法由人工進(jìn)行控制的,例如寫文件失敗網(wǎng)絡(luò)連接超時(shí),數(shù)據(jù)庫數(shù)據(jù)傳輸失敗或者從網(wǎng)絡(luò)接收到的數(shù)據(jù)已經(jīng)損壞。通過控制Mock Object我們很容易就可以模擬上面的這些情況。

3.3.2 模擬對(duì)象作為設(shè)計(jì)手段的優(yōu)點(diǎn)

雖然Mock Object最直接的優(yōu)點(diǎn)在于給予測(cè)試代碼更多的可控性和可操作性,它最大的優(yōu)點(diǎn)在于對(duì)軟件設(shè)計(jì)的影響[3]。

(1)測(cè)試驅(qū)動(dòng)開發(fā)與Mock Object一起使用,可以寫出低耦合高內(nèi)聚,非常優(yōu)雅干凈的代碼。

(2)強(qiáng)迫設(shè)計(jì)者放棄對(duì)第三方庫的強(qiáng)依賴關(guān)系,取而代之的是比較弱的依賴關(guān)系。

(3)設(shè)計(jì)人員可以將更大的注意力放在商業(yè)邏輯的實(shí)現(xiàn)和測(cè)試.由于Mock Object的存在,我們不需要實(shí)現(xiàn)數(shù)據(jù)訪問層就可以對(duì)商業(yè)邏輯進(jìn)行測(cè)試。而商業(yè)邏輯才是任何系統(tǒng)中對(duì)于客戶最重要的內(nèi)容,它的正確與否決定了整個(gè)系統(tǒng)是否能完成任務(wù),它的穩(wěn)定性決定了整個(gè)系統(tǒng)架構(gòu)的穩(wěn)定性。

(4)在項(xiàng)目初期,甚至是中期,將設(shè)計(jì)人員解放出來,不用對(duì)系統(tǒng)底層的基礎(chǔ)設(shè)施做出判斷。例如,在商業(yè)邏輯并不明確,需求還不穩(wěn)定的時(shí)候,我們是更多根據(jù)感覺來做出很多重要的判斷的,而這些判斷往往導(dǎo)致比較關(guān)鍵的決定。例如,在項(xiàng)目之初,誰能夠明確的回答到底需要什么樣的數(shù)據(jù)庫?Oracle?SQL Server?還是XML文件?到底需要什么樣的隊(duì)列服務(wù)器 MSMQ還是IBM—MQ?由于Mock Object的引入,我們可以將這些決策推遲到商業(yè)邏輯層更加明確之后進(jìn)行,從而可以獲得更加準(zhǔn)確有針對(duì)性的答案。

3.4 模擬對(duì)象的局限性

Mock Object在實(shí)際項(xiàng)目中的應(yīng)用存在一些限制,一些是由于Mock Object本身性質(zhì)決定的,有一些則是由于其它類庫設(shè)計(jì)存在的缺陷導(dǎo)致的。

(1)一個(gè)典型的不是Mock Object的問題,而是類庫設(shè)計(jì)的問題。是Mock Object無法模擬比較深的對(duì)象樹。有一些第三方的類庫,尤其是一些消息處理函數(shù)的參數(shù),提供的不是接口而是一些對(duì)象。往往這些對(duì)象內(nèi)部有很多子對(duì)象,也就是我們常說的一棵大的對(duì)象樹。我們需要花費(fèi)太多的精力去構(gòu)造這些對(duì)象來進(jìn)行模擬,時(shí)間消耗巨大。

(2)一般性而言,單元測(cè)試的粒度越細(xì),功能測(cè)試的粒度就可以越粗[4]。但是引入Mock Object的單元測(cè)試仍然無法取代功能測(cè)試。一個(gè)很好的例子就是誤差積累的測(cè)試,哪怕每個(gè)單元的誤差都在可接收范圍內(nèi),我們?nèi)匀恍枰粋€(gè)功能測(cè)試確保整體誤差也是可以接受的。

4 結(jié)束語

模擬對(duì)象解決了傳統(tǒng)單元測(cè)試的兩個(gè)問題:一是如何將需要測(cè)試的代碼與相關(guān)環(huán)境隔離;二是如何創(chuàng)建一個(gè)快速、可控的環(huán)境輔助測(cè)試開發(fā)。隨著模擬對(duì)象技術(shù)的成熟,基于模擬對(duì)象的單元測(cè)試會(huì)越來越廣泛地被采用。

參考文獻(xiàn):

[1]Kent Beck.測(cè)試驅(qū)動(dòng)開發(fā)[M].北京:中國(guó)電力出版社,2003.

[2]Myers.王峰,陳杰譯.軟件測(cè)試的藝術(shù)(第二版)[M]. 北京:機(jī)械工業(yè)出版社,2006.50-52.

[3]David Astels.崔凱,譯.測(cè)試驅(qū)動(dòng)開發(fā)實(shí)用指南[M].北京:中國(guó)電力出版社,2004.120-130.

[4]Paul C Jorgensen.韓柯,杜旭濤,譯.軟件測(cè)試(第二版)[M].北京:機(jī)械工業(yè)出版社,2003.

收稿日期:2007-12-15

作者簡(jiǎn)介:劉赟(1980-),男,碩士,研究方向:軟件工程。

主站蜘蛛池模板: 日韩国产亚洲一区二区在线观看| 免费看美女毛片| 欧美天堂在线| 久久久久亚洲精品无码网站| 热99精品视频| 亚洲中文字幕久久精品无码一区| 日韩精品一区二区三区免费在线观看| 久久国产精品波多野结衣| 欧美中文一区| 国产精品流白浆在线观看| 第九色区aⅴ天堂久久香| 国产精品亚洲va在线观看| 波多野结衣一区二区三视频| 亚洲视频无码| 国产成人精品亚洲日本对白优播| 欧美日韩国产在线人成app| 亚洲中文字幕av无码区| 波多野结衣无码AV在线| 农村乱人伦一区二区| 无码福利视频| 亚洲高清中文字幕在线看不卡| 国产激情第一页| 亚洲欧美精品一中文字幕| 免费人成视网站在线不卡| 欧美国产精品不卡在线观看| 日韩欧美在线观看| 欧美日韩亚洲综合在线观看| 欧美影院久久| 国产另类乱子伦精品免费女| 国产亚卅精品无码| 老司机aⅴ在线精品导航| 成人在线视频一区| 国产乱子伦视频在线播放| 国产99欧美精品久久精品久久| 国产又色又爽又黄| 久久这里只有精品免费| 亚洲三级成人| AV熟女乱| 丁香婷婷激情网| 国产精品免费久久久久影院无码| 欧美一区二区三区国产精品| 国产日韩丝袜一二三区| 91国内视频在线观看| 91av国产在线| 亚洲成a∧人片在线观看无码| 欧美亚洲国产精品第一页| 国产91熟女高潮一区二区| 亚洲男人天堂久久| 国产一级做美女做受视频| 亚洲av无码久久无遮挡| 国产精品成人啪精品视频| 久久精品国产免费观看频道| 亚洲成人在线免费观看| 青青极品在线| 久久国产精品电影| 蜜臀av性久久久久蜜臀aⅴ麻豆| 国产福利在线观看精品| 成年人久久黄色网站| 久久久91人妻无码精品蜜桃HD | 国产成人AV男人的天堂| igao国产精品| 国产美女视频黄a视频全免费网站| 日本不卡在线播放| 亚洲天堂视频在线播放| 午夜啪啪福利| 日本欧美在线观看| 老司机精品一区在线视频| 综合人妻久久一区二区精品| 孕妇高潮太爽了在线观看免费| 久久亚洲综合伊人| 天天综合色天天综合网| 啪啪啪亚洲无码| 国产91色| 国产白浆一区二区三区视频在线 | 91麻豆国产视频| 首页亚洲国产丝袜长腿综合| 91欧美在线| 亚洲无线视频| 一区二区欧美日韩高清免费| …亚洲 欧洲 另类 春色| 国产精品护士| 国产第一页免费浮力影院|