《軟件測試》課件第7章_第1頁
《軟件測試》課件第7章_第2頁
《軟件測試》課件第7章_第3頁
《軟件測試》課件第7章_第4頁
《軟件測試》課件第7章_第5頁
已閱讀5頁,還剩260頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

項目七開源網(wǎng)絡(luò)硬盤系統(tǒng)測試7.1問題情境7.2問題分析7.3任務(wù)設(shè)計與實施7.4知識總結(jié)7.5應(yīng)用實踐

有一個開源網(wǎng)絡(luò)硬盤系統(tǒng),完成對該系統(tǒng)中部分模塊代碼的單元測試以及系統(tǒng)的集成測試和壓力測試。7.1問題情境

分析系統(tǒng)功能,系統(tǒng)由文件目錄維護(新建目錄、壓縮目錄、解壓縮、剪切、復(fù)制、粘貼)、文件上傳、文件下載三個功能模塊組成,如圖7-1所示。應(yīng)先完成對每個模塊類文件中獨立函數(shù)的單元測試,再完成對系統(tǒng)核心類——FileAction類中函數(shù)調(diào)用功能的集成測試,最后完成對系統(tǒng)的壓力測試。7.2問題分析圖7-1系統(tǒng)運行截圖

7.3.1設(shè)計完成系統(tǒng)部分模塊的單元測試

測試程序開發(fā)運行環(huán)境:MyEclipse6.6

+

Resin4.1

+

JDK1.5_18

+

Junit4.4。選擇packagecom.lhq.prj.dd.core包下的MyUtils類文件作為單元測試類。本例中對isFileExist()方法進行單元測試,建立測試用例。目標(biāo)函數(shù)源代碼如下:

/**7.3任務(wù)設(shè)計與實施 *判斷文件是否存在

*

*@paramfileName

*@paramdir

*@returnboolean

*/

public

static

booleanisFileExist(StringfileName,Stringdir){

Filefiles=newFile(dir+fileName);

return(files.exists())?true:false;

}對源代碼分析如下:此方法中返回值為boolean類型,有兩個分支,即true和false。因此,單元測試需對兩條分支分別進行測試。

(1)假設(shè)在本地D盤根目錄下存在文件jdbcurl.txt,編寫測試用例代碼如下:

packagecom.lhq.prj.dd.core.test;

importorg.junit.After;

importorg.junit.AfterClass;

importorg.junit.Assert;

importorg.junit.Before;

importorg.junit.Test;

importcom.lhq.prj.dd.core.MyUtils;

public

classMyUtilsTest{

StringfileName;

Stringdir;

@AfterClass

public

static

voidtearDownAfterClass()throwsException{

}

@Before

public

voidsetUp()throwsException{

fileName="jdbcurl.txt";

dir="D:\\";

}

@After

public

voidtearDown()throwsException{

}

@Test

public

final

voidtestIsFileExist(){

//fail("Notyetimplemented");//TODO

Assert.assertTrue(MyUtils.isFileExist(fileName,dir));

}

}

運行測試用例,如圖7-2所示。圖7-2運行測試開始圖7-3測試通過

(2)另外一種情況是,測試本地D盤根目錄下不存在的文件test.txt。測試用例代碼MyUtilsTest.java如下:

packagecom.lhq.prj.dd.core.test;

importorg.junit.After;

importorg.junit.AfterClass;

importorg.junit.Assert;

importorg.junit.Before;

importorg.junit.Test;

importcom.lhq.prj.dd.core.MyUtils;

public

classMyUtilsTest{

StringfileName;

Stringdir;

@AfterClass

public

static

voidtearDownAfterClass()throwsException{

}

@Before

public

voidsetUp()throwsException{

//fileName="jdbcurl.txt";

fileName="test.txt";

dir="D:\\";

}

@After

public

voidtearDown()throwsException{

}

@Test

public

final

voidtestIsFileExist(){

//fail("Notyetimplemented");//TODO

Assert.assertFalse(MyUtils.isFileExist(fileName,dir));

}

}圖7-4測試失敗7.3.2設(shè)計完成系統(tǒng)的集成測試

本例中需設(shè)計并完成對系統(tǒng)中FileAction類的集成測試。為了脫離J2EE容器進行孤立測試,本例中使用EasyMock結(jié)合JUnit進行集成測試。

EasyMock主要是為測試提供模擬數(shù)據(jù),比如可以模擬HttpServletRequest。使用EasyMock的一般步驟為:

(1)創(chuàng)建一個mock對象;

(2)設(shè)置此對象的某個方法的返回值;

(3)保存被mock的對象;

(4)應(yīng)用mock對象;

(5)驗證所設(shè)置的mock對象是否按預(yù)期運行。

分析FileAction類的源代碼,代碼涉及父類BaseAction及MyUtils工具類。以createFolder()函數(shù)和deleteFiles()函數(shù)為例編寫測試用例代碼FileActionTest.java如下:

packagecom.lhq.prj.dd.action;

importorg.junit.After;

importorg.junit.AfterClass;

importorg.junit.Before;

importorg.junit.Test;

importorg.junit.Assert;

importorg.easymock.classextension.EasyMock;

importorg.easymock.classextension.EasyMockSupport;

importcom.lhq.prj.dd.action.FileAction;

importcom.opensymphony.xwork2.ActionSupport;

public

classFileActionTestextendsEasyMockSupport{

FileActionfileActionObj;

FileActionfileActionObj2;

@AfterClass

public

static

voidtearDownAfterClass()throwsException{

}

@Before

public

voidsetUp()throwsException{

fileActionObj=EasyMock.createMockBuilder(FileAction.class).addMockedMethods("getRootPath","getName","getPath").createMock();

fileActionObj2=EasyMock.createMockBuilder(FileAction.class).addMockedMethod("getRootPath").createMock();

}

@After

public

voidtearDown()throwsException{

}

@Test

public

final

voidtestCreateFolder()throwsException{

//fail("Notyetimplemented");//TODO

EasyMock.expect(fileActionObj.getRootPath()).andReturn("D:\\resin-4.0.1\\webapps\\

dogdisk\\");

EasyMock.expect(fileActionObj.getName()).andReturn("test");

EasyMock.expect(fileActionObj.getPath()).andReturn("");

EasyMock.replay(fileActionObj);

Assert.assertEquals(ActionSupport.SUCCESS,fileActionObj.createFolder());

EasyMock.verify(fileActionObj);

}

@Test

public

final

voidtestDeleteFiles()throwsException{

EasyMock.expect(fileActionObj2.getRootPath()).andReturn("D:\\resin-4.0.1\\webapps\\

dogdisk\\");

fileActionObj2.setPaths(newString[]{"test2","test3"});

EasyMock.replay(fileActionObj2);

Assert.assertEquals(ActionSupport.SUCCESS,fileActionObj2.deleteFiles());

EasyMock.verify(fileActionObj2);

}

}測試之前,在目錄D:\resin-3.1.9\webapps\dogdisk\root下創(chuàng)建文件夾test2和test3,作為deleteFiles()函數(shù)的測試文件夾,如圖7-5所示。圖7-5執(zhí)行測試前的目錄結(jié)構(gòu)對createFolder()函數(shù)執(zhí)行testCreateFolder()進行測試,如圖7-6所示。在D:\resin-3.1.9\webapps\dogdisk\root目錄下創(chuàng)建test目錄,如圖7-7所示。對deleteFiles()函數(shù)執(zhí)行testDeleteFiles()進行測試,刪除D:\resin-3.1.9\webapps\dogdisk\root目錄下的test2和test3目錄。執(zhí)行測試結(jié)果如圖7-8所示。圖7-6執(zhí)行測試程序圖7-7執(zhí)行測試后的目錄結(jié)構(gòu)圖7-8執(zhí)行測試后的結(jié)果7.3.3設(shè)計完成系統(tǒng)的壓力測試

JMeter是Apache組織的開放源代碼的工具,它是功能和性能測試的工具,最新的版本是1.9.1,可以到/jmeter/index.html下載源代碼并查看相關(guān)文檔。

JMeter可以用于測試靜態(tài)或者動態(tài)資源(文件、Servlets、Perl腳本、java對象、數(shù)據(jù)庫和查詢、ftp服務(wù)器或者其他的資源)的性能。JMeter用于測試在服務(wù)器、網(wǎng)絡(luò)或者其他對象上附加高負載后這些對象的受壓能力,或者分析它們提供的服務(wù)在不同負載條件下的總性能情況。用戶可以用JMeter提供的圖形化界面分析性能指標(biāo)或者在高負載情況下測試服務(wù)器/腳本/對象的行為。

使用JMeter測試Web應(yīng)用的步驟如下:

第一步:準(zhǔn)備測試環(huán)境。本書中使用Resin作為Web服務(wù)器進行測試,被測試的內(nèi)容是上述系統(tǒng)的首頁。

第二步:安裝啟動JMeter。可以到/site/downloads/downloads_

jmeter.cgi下載JMeter的release版本,然后將下載的.zip文件解壓縮到D:/jakarta-jmeter-2.3.4目錄下。接著使用

%jakarta-jmeter-2.3.4%/bin下面的jmeter.bat批處理文件來啟動JMeter的可視化界面,下面的工作都將在這個可視化界面上進行操作。JMeter的可視化界面的屏幕截圖如圖7-9所示。圖7-9JMeter的可視化界面第三步:建立測試計劃(TestPlan)。測試計劃描述了執(zhí)行測試過程中JMeter的執(zhí)行過程和步驟。一個完整的測試計劃包括一個或者多個線程組(ThreadGroups)、邏輯控制(LogicController)、實例產(chǎn)生控制器(SampleGeneratingControllers)、偵聽器(Listener)、定時器(Timer)、比較(Assertions)、配置元素(ConfigElements)。打開JMeter時,它已經(jīng)建立了一個默認的測試計劃。一個JMeter應(yīng)用的實例只能建立或者打開一個測試計劃?,F(xiàn)在開始填充一個測試計劃的內(nèi)容,這個測試計劃向一個jsp文件和一個servlet發(fā)出請求,我們需要JMeter模擬五個請求者(也就是五個線程),每個請求者連續(xù)請求兩次,下面幾步是詳細的操作步驟。

第四步:增加負載信息設(shè)置。向測試計劃中增加相關(guān)負載設(shè)置,讓Jmeter知道需要模擬五個請求者,每個請求者在測試過程中連續(xù)請求兩次。詳細步驟為:選中可視化界面中左邊樹的測試計劃節(jié)點,單擊右鍵,選擇添加—線程組,界面右邊將會出現(xiàn)設(shè)置信息框。線程組有如下三個和負載信息相關(guān)的參數(shù):

(1)線程數(shù):設(shè)置發(fā)送請求的用戶數(shù)目。

(2)

Ramp-UpPeriod:每個請求發(fā)生的總時間間隔,單位是秒。若請求數(shù)目是5,而這個參數(shù)是10,那么每個請求之間的間隔就是10/5,也就是2秒。

(3)循環(huán)次數(shù):請求發(fā)生的重復(fù)次數(shù)。如果選擇后面的“永遠”(默認),那么請求將一直繼續(xù);如果不選擇“永遠”,而在輸入框中輸入數(shù)字,那么請求將重復(fù)指定的次數(shù);如果輸入0,那么請求將被執(zhí)行一次。根據(jù)任務(wù)要求的設(shè)計,我們應(yīng)該將線程數(shù)設(shè)置為5,Ramp-UpPeriod設(shè)置為0(也就是同時并發(fā)請求),不選中“永遠”,在循環(huán)次數(shù)后面的輸入框中輸入2,設(shè)置后的屏幕截圖如圖7-10所示。圖7-10設(shè)置好參數(shù)的線程組第五步:增加默認HTTP屬性。實際的測試工作往往是針對同一個服務(wù)器上的Web應(yīng)用展開的,所以Jmeter提供了這樣一種設(shè)置:在默認HTTP屬性中設(shè)置需要被測試服務(wù)器的相關(guān)屬性,在以后的HTTP請求設(shè)置中就可以忽略這些相同參數(shù)的設(shè)置,以減少設(shè)置參數(shù)錄入的時間。

可以通過下面的步驟來設(shè)置默認HTTP屬性:

(1)選中可視化界面中左邊樹的測試計劃節(jié)點,單擊右鍵,選擇添加—配置元件—請求默認值,界面右邊將會出現(xiàn)設(shè)置信息框。

(2)默認HTTP屬性的主要參數(shù):

服務(wù)器名稱或IP:被測試服務(wù)器的IP地址或者名稱。

端口號:服務(wù)器提供服務(wù)的端口號。

Connect:連接超時時間(毫秒)。

Response:響應(yīng)超時時間(毫秒)。

協(xié)議:發(fā)送測試請求時使用的協(xié)議。

contentencoding:字符集設(shè)置。

路徑:默認的起始位置。比如將路徑設(shè)置為/diskdog,那么所有的HTTP請求的url中都將增加

/diskdog路徑。

測試計劃將針對本機的Web服務(wù)器上的Web應(yīng)用進行測試,所以協(xié)議應(yīng)該是http,IP使用localhost。因為這個Web應(yīng)用發(fā)布的context路徑是

/diskdog,所以這里的路徑設(shè)置為/diskdog,因為使用Tomcat服務(wù)器,所以端口號是8080。設(shè)置后的屏幕截圖如圖7-11所示。圖7-11測試計劃中使用的默認HTTP參數(shù)第六步:增加HTTP請求?,F(xiàn)在需要增加HTTP請求,這是測試的內(nèi)容主體部分??梢酝ㄟ^下面的步驟來增加HTTP請求:

(1)選中可視化界面中左邊樹的ThreadGroup節(jié)點,單擊右鍵,選擇添加—sampler—HTTP請求,界面右邊將會出現(xiàn)設(shè)置信息框。

(2)增加的屬性中有發(fā)送HTTP時方法的選擇,可以選擇為GET或者POST。我們現(xiàn)在增加一個HTTP請求,由于已經(jīng)設(shè)置了默認的HTTP屬性,所以和默認HTTP屬性中相同的屬性不再重復(fù)設(shè)置。設(shè)置后的屏幕截圖如圖7-12所示。圖7-12設(shè)置好的jsp測試請求第七步:增加Listener。增加listener是為了記錄測試信息,并且可以使用Jmeter提供的可視化界面查看測試結(jié)果。其中有多種結(jié)果分析方式可供選擇,可以根據(jù)自己習(xí)慣的分析方式選擇不同的結(jié)果顯示方式,這里使用表格的形式來查看和分析測試結(jié)果。讀者可以通過下面的步驟來增加listener:

(1)選中可視化界面中左邊樹的測試計劃節(jié)點,單擊右鍵,選擇添加—監(jiān)聽器—用表格查看結(jié)果,界面右邊將會出現(xiàn)設(shè)置信息和結(jié)果顯示框。

(2)可以通過界面上面的文件名屬性設(shè)置,將測試結(jié)果保存到某個文件中,界面下面將使用表格顯示測試結(jié)果。

在界面的最下面還可以看到一些統(tǒng)計信息,最關(guān)心的應(yīng)該是Average,也就是相應(yīng)的平均時間。

第八步:開始執(zhí)行測試計劃??梢酝ㄟ^單擊菜單欄運行—啟動,開始執(zhí)行測試計劃。圖7-13和圖7-14分別是第一次、第二次執(zhí)行該測試計劃的結(jié)果。圖7-13第一次執(zhí)行后的結(jié)果顯示圖7-14第二次執(zhí)行后的結(jié)果顯示從上面兩幅圖中可以看到,第一次執(zhí)行時的幾個時間較長,這是由于jsp執(zhí)行前都需要被編譯成

.class文件,所以第二次執(zhí)行的結(jié)果才是正常的結(jié)果。

JMeter用于進行功能或者性能測試,通過使用JMeter提供的功能,我們可以可視化地制定測試計劃,包括規(guī)定使用什么樣的負載、測試什么內(nèi)容、傳入什么參數(shù)。同時,它也提供了多種圖形化的測試結(jié)果顯示方式,使我們能夠簡便地開始測試工作并分析測試結(jié)果。

7.4.1單元測試

下面舉例說明單元測試。

假如寫了如下的加法函數(shù):

intadd(inta,intb)

{7.4知識總結(jié)

returna-b;

}

該函數(shù)可實現(xiàn)兩數(shù)相加,并得到結(jié)果。例如輸入兩個1,就會返回它們的和2,編寫其驅(qū)動程序并執(zhí)行。

voidtest_add()

{

inta=1;

intb=1;

intret=add(a,b);

ASSERT(ret==2);

}

intmain()

{

test_add();

}

該函數(shù)的執(zhí)行結(jié)果不是2,而是0,說明此函數(shù)存在錯誤。

1.引言

單元測試是在軟件開發(fā)過程中要進行的最低級別的測試活動。在單元測試活動中,軟件的獨立單元將在與程序的其他部分相隔離的情況下進行測試。

在傳統(tǒng)的結(jié)構(gòu)化編程語言,比如C語言中,要進行測試的單元一般是函數(shù)或子過程。在像C++這樣的面向?qū)ο蟮恼Z言中,要進行測試的基本單元是類。對Ada語言來說,開發(fā)人員可以選擇是在獨立的過程和函數(shù)上還是在Ada包的級別上進行單元測試。單元測試的原則同樣被擴展到第四代語言(4GL)的開發(fā)中,在這里基本單元被典型地劃分為一個菜單或顯示界面。單元測試不僅僅作為無錯編碼的一種輔助手段在一次性的開發(fā)過程中使用,而且在軟件修改或是移植到新的運行環(huán)境的過程中還將重復(fù)使用。因此,所有的測試都必須在整個軟件系統(tǒng)的生命周期中進行維護。

單元測試(模塊測試)是開發(fā)者編寫的一小段代碼,用于檢驗被測代碼的一個很小的、很明確的功能是否正確。通常而言,一個單元測試用于判斷某個特定條件(或者場景)下某個特定函數(shù)的行為。例如,可能把一個很大的值放入一個有序列表中去,然后確認該值出現(xiàn)在列表的尾部;或者可能會從字符串中刪除匹配某種模式的字符,然后確認字符串確實不再包含這些字符了。不同情況下單元的概念有以下幾種:

“單元”:明確的功能、規(guī)格定義,明確的與其他部分的接口定義;

結(jié)構(gòu)化程序設(shè)計:函數(shù)或子過程;

面向?qū)ο螅侯惢蝾惖姆椒ǎ?/p>

一個菜單、屏幕顯示界面或?qū)υ捒虻取?/p>

經(jīng)常與單元測試聯(lián)系起來的另外一些開發(fā)活動包括代碼走讀(CodeReview)、靜態(tài)分析(StaticAnalysis)和動態(tài)分析(DynamicAnalysis)。靜態(tài)分析就是對軟件的源代碼進行研讀,查找錯誤或收集一些度量數(shù)據(jù),并不需要對代碼進行編譯和執(zhí)行。動態(tài)分析就是通過觀察軟件運行時的動作來提供執(zhí)行跟蹤、時間分析以及測試覆蓋度方面的信息。

2.單元測試的定義

單元測試也稱模塊測試,是針對最小的可測試軟件元素——模塊進行正確性檢驗的測試工作,其目的在于發(fā)現(xiàn)各模塊內(nèi)部可能存在的各種差錯。單元測試的依據(jù)是詳細設(shè)計描述。單元測試的內(nèi)容包括單元的內(nèi)部結(jié)構(gòu)(如邏輯和數(shù)據(jù)流)以及單元的功能和可觀測的行為。通常,我們使用白盒測試方法測試單元的內(nèi)部結(jié)構(gòu),使用黑盒測試方法測試單元的功能和可觀測的行為。

3.單元測試的原因

在編寫代碼時,一定會反復(fù)調(diào)試以保證它能夠編譯通過。如果代碼未通過編譯,沒有任何人會愿意將其交付給負責(zé)人。但即使代碼通過了編譯,只是說明它的語法正確,卻無法保證它的語義也一定正確,即這段代碼的行為一定是正確的。

4.單元測試的特點

(1)單元測試是一種驗證行為。程序中的每一項功能都通過單元測試來驗證它的正確性,它為以后的開發(fā)提供支援。就算是開發(fā)后期,我們也可以輕松地增加功能或更改程序結(jié)構(gòu),而不用擔(dān)心在這個過程中會破壞重要的東西。而且它為代碼的重構(gòu)提供了保障。這樣,我們就可以更好地對程序進行改進。

(2)單元測試是一種設(shè)計行為。編寫單元測試將使我們從調(diào)用者的角度觀察、思考。特別是先寫測試(testfirst),迫使我們把程序設(shè)計成易于調(diào)用和可測試的,即迫使我們解除軟件中的耦合。

(3)單元測試是一種編寫文檔的行為。單元測試所編寫的文檔是一種無價的文檔,是展示函數(shù)或類如何使用的最佳文檔。這份文檔是可編譯、可運行的,并且它能保持是最新的,永遠與代碼同步。

(4)單元測試具有回歸性。自動化的單元測試避免了代碼回歸。單元測試腳本編寫完成之后,可以快速運行測試。

5.單元測試的范疇

如果要給單元測試定義一個明確的范疇,指出哪些功能屬于單元測試,這似乎很難。但下面討論的四個問題,基本上可以說明單元測試的范疇,即單元測試所要做的工作。

(1)單元測試的行為和期望的一致嗎?這是單元測試最根本的目的,我們就是用單元測試的代碼來證明它所做的就是我們所期望的。

(2)單元測試的行為一直和期望的一致嗎?編寫單元測試程序,如果只測試代碼的一條正確路徑,讓它正確走一遍,并不算是真正的完成。軟件開發(fā)是一項復(fù)雜的工程,在測試某段代碼的行為是否和期望的一致時,需要確認:在任何情況下,這段代碼是否都和期望一致,譬如在參數(shù)很可疑、硬盤沒有剩余空間、緩沖區(qū)溢出、網(wǎng)絡(luò)掉線的情況下。

(3)可以依賴單元測試嗎?不能依賴的代碼是沒有多大用處的。既然單元測試是用來保證代碼的正確性的,那么單元測試也一定要值得依賴。

(4)單元測試說明意圖了嗎?單元測試能夠幫助測試人員充分了解代碼的用法。從效果上看,單元測試就像是能執(zhí)行的文檔,它說明了在用各種條件調(diào)用代碼時,期望這段代碼完成的功能。

6.單元測試環(huán)境

單元測試環(huán)境建立的原因是由于一個模塊或一個方法與外界的聯(lián)系是必然的。在單元測試時,如果模塊不是獨立的程序,則需要輔助測試模塊。

輔助模塊有兩種:

(1)驅(qū)動模塊:所測模塊的主程序。它接收測試數(shù)據(jù),再把這些數(shù)據(jù)傳遞給所測試模塊,最后輸出實測結(jié)果。當(dāng)被測試模塊能完成一定功能時,也可以不要驅(qū)動模塊。

(2)樁模塊:用來代替所測模塊調(diào)用的子模塊。

被測試模塊、驅(qū)動模塊和樁模塊共同構(gòu)成了一個測試環(huán)境,如圖7-15所示。

圖7-15單元測試環(huán)境

7.單元測試策略

1)自頂向下的單元測試策略

步驟:

(1)從最頂層開始,把頂層調(diào)用的單元做成樁模塊。

(2)對第二層進行測試,使用上面已測試的單元做驅(qū)動模塊。

(3)依此類推,直到全部單元測試結(jié)束。優(yōu)點:它可以在集成測試之前為系統(tǒng)提供早期的集成途徑。由于詳細設(shè)計一般都是自頂向下進行設(shè)計的,因此自頂向下的單元測試策略在執(zhí)行上同詳細設(shè)計的順序一致。該測試方法可以和詳細設(shè)計及編碼進行重疊操作。缺點:

(1)單元測試被樁模塊控制,隨著單元一個一個被測試,測試過程將變得越來越復(fù)雜,并且測試和維護成本都將不斷增加。

(2)低層次的結(jié)構(gòu)覆蓋率難以得到保證。

(3)更改任何一個單元時,就必須重新測試該單元下層調(diào)用的所有單元(因為上層驅(qū)動改變)。

(4)底層單元的測試必須等待頂層單元測試完畢后才能進行,無法進行并行測試,測試周期將被延長。

總結(jié):自頂向下的單元測試策略要做樁模塊,其成本要高于孤立的單元測試成本,因此從測試成本方面來考慮,它并不是最佳的單元測試策略。

2)自底向上的單元測試策略

步驟:

(1)先對模塊調(diào)用圖上的最底層模塊進行測試,模擬調(diào)用該模塊的模塊為驅(qū)動模塊。

(2)對上一層模塊進行單元測試,用已經(jīng)被測試過的模塊做樁模塊。

(3)依此類推,直到全部單元測試結(jié)束。

優(yōu)點:不需要單獨設(shè)計樁模塊。

缺點:

(1)隨著單元測試的不斷進行,測試過程會變得越來越復(fù)雜,測試周期延長,測試和維護的成本都將增加。

(2)隨著各個基本單元的逐步加入,系統(tǒng)會變得異常龐大,因此測試人員不容易控制。

(3)越接近頂層的模塊的測試其結(jié)構(gòu)覆蓋率就越難以保證。

(4)任何一個模塊修改之后,直接或間接調(diào)用該模塊的所有單元都要重新測試(因為調(diào)用的下層程序改變)。

(5)并行性不好。

(6)不能和詳細設(shè)計、編碼同步進行。

3)孤立測試

步驟:不考慮每個模塊與其他模塊之間的關(guān)系,分別為每個模塊單獨設(shè)計樁模塊和驅(qū)動模塊,逐一完成所有單元模塊的測試。優(yōu)點:簡單、容易操作,因此所需測試時間短,能夠達到高覆蓋率。

缺點:不能為集成測試提供早期的集成途徑,而且依賴結(jié)構(gòu)設(shè)計信息,需要設(shè)計多個樁模塊和驅(qū)動模塊,增加了額外的測試成本。

總結(jié):該方法是比較理想的單元測試方法,如再輔助以適當(dāng)?shù)募蓽y試策略,有利于縮短項目的開發(fā)時間。

4)綜合測試

在單元測試中,為了有效地減少開發(fā)樁模塊的工作量,可以考慮綜合自底向上測試策略和孤立測試策略。

8.單元測試分析

從如下幾方面進行分析和測試:

(1)判斷得到的結(jié)果是否正確。

(2)判斷是否滿足所有的邊界條件,包括:

輸入一個格式錯誤的數(shù)據(jù)。

提供一個空值或者不完整的值。

輸入與意料之中的值相差很遠的值。

若要求唯一,可以輸入兩個或多個相同的數(shù)值來進行測試。

如果要求按照一定的順序來存儲一些數(shù)據(jù),那么可以輸入一些順序打亂的數(shù)據(jù)來做測試。

對于一些做了安全限制的部分,盡量通過各種途徑嘗試能否繞過安全限制的測試。例如,ATM取款未輸入密碼,能否顯示余額和取款。

如果功能的啟用有一定的順序限制,就用和期望不一致的順序來進行測試。

(3)分析能否使用反向關(guān)聯(lián)檢查。例如,檢查插入功能是否正確,可以使用查詢驗證。

(4)分析是否能使用其他手段來交叉檢查一下結(jié)果。一般而言,對某個值進行計算會有一種以上的算法,但我們會因考慮運行效率或其他方面的原因而選擇其中的一種,例如判斷三角形全等。

(5)分析是否可以強制一些錯誤發(fā)生,例如網(wǎng)絡(luò)故障、內(nèi)存不足、磁盤空間不足等。

(6)分析模塊接口,例如在數(shù)據(jù)能正確流入、流出模塊的前提下,其他測試才有意義。

(7)分析局部數(shù)據(jù)結(jié)構(gòu)。

(8)分析獨立路徑,保證每條語句至少被執(zhí)行一次。

(9)分析出錯處理是否正確,預(yù)設(shè)各種出錯處理通路。

9.單元測試用例設(shè)計

(1)測試的完整性度量以白盒測試為主:

語句覆蓋(100%);

判定覆蓋(100%);

條件覆蓋;

判定/條件覆蓋;

路徑覆蓋(主要)。

(2)測試用例的四個關(guān)鍵元素:

初始狀態(tài)聲明;

輸入數(shù)據(jù);

實際測試的代碼;

期望輸出結(jié)果。

1)測試用例設(shè)計步驟

步驟1:使被測單元運行,(盡量簡單)適合的技術(shù)有下面兩種:

由模塊設(shè)計說明導(dǎo)出測試;

對等區(qū)間劃分。

步驟2:正面測試(PositiveTesting),適合的技術(shù)有下面三種:

由設(shè)計說明導(dǎo)出測試;

對等區(qū)間劃分;

狀態(tài)轉(zhuǎn)換測試。

步驟3:負面測試(NegativeTesting),適合的技術(shù)有以下四種:

錯誤猜測;

邊界值分析;

內(nèi)部邊界值測試;

狀態(tài)轉(zhuǎn)換測試。步驟4:模塊設(shè)計需求中其他測試用例的設(shè)計,例如性能、余量、安全等。

步驟5:覆蓋率測試用例設(shè)計,適合的技術(shù)有以下四種:

分支測試;

條件測試;

數(shù)據(jù)定義——使用測試;

狀態(tài)轉(zhuǎn)換測試。

步驟6:測試執(zhí)行。

步驟7:完善代碼覆蓋,適合的技術(shù)有下面四種:

分支測試;

條件測試;

設(shè)計定義——試驗測試;

狀態(tài)轉(zhuǎn)換測試。

2)面向?qū)ο髴?yīng)用程序的單元測試用例設(shè)計

(1)功能性測試,有以下兩種:

類的規(guī)格說明(概念和方法);

方法的規(guī)格說明(前置/后置條件)。

(2)結(jié)構(gòu)性測試,類作為一個單元來進行測試,有以下兩種:

方法的單獨測試;

方法的綜合測試。

3)基于對象—狀態(tài)轉(zhuǎn)移圖的OO軟件測試

節(jié)點:表示對象的某個可能狀態(tài);

有向邊:事件/動作。

如圖7-16所示,當(dāng)對象處于狀態(tài)A時,若接收到事件e,則執(zhí)行相應(yīng)的操作a并轉(zhuǎn)移到狀態(tài)B。

圖7-16對象—狀態(tài)轉(zhuǎn)換圖

(1)狀態(tài)的處理。列出對象的邏輯狀態(tài),而非所有實際狀態(tài)。理論上,所有數(shù)據(jù)成員狀態(tài)的笛卡爾積都應(yīng)列出,實際上不可能全部列出,類似等價類劃分。

(2)主要步驟。

依據(jù)設(shè)計文檔,或者通過分析對象數(shù)據(jù)成員的取值情況空間,得到被測試類的狀態(tài)轉(zhuǎn)移圖。

給被測試的類加入用于設(shè)置和檢查對象狀態(tài)的新方法,例如set()、get()等,導(dǎo)出對象的邏輯狀態(tài)。

確定狀態(tài)轉(zhuǎn)移圖中的每個狀態(tài)是哪些方法的合法起始狀態(tài),即在該狀態(tài)時,對象允許執(zhí)行哪些操作。

在每個狀態(tài),從類中方法的調(diào)用關(guān)系圖最下層開始,逐一測試類中的方法。

測試每個方法時,根據(jù)對象的當(dāng)前狀態(tài)確定對方法的執(zhí)行路徑有特殊影響的參數(shù)值,將各種可能組合作為參數(shù)進行測試。

4)類的數(shù)據(jù)流測試

類的數(shù)據(jù)流測試是一種白盒測試方法,它利用程序的數(shù)據(jù)流之間的關(guān)系來指導(dǎo)測試的選擇。對類的數(shù)據(jù)流應(yīng)進行三級測試,定義如下:

(1)方法內(nèi)部測試:測試單個方法,相當(dāng)于單元測試。

(2)方法間測試:在類中測試一個直接或間接調(diào)用的公開方法,相當(dāng)于集成測試。

(3)類內(nèi)部測試:測試公開方法在各種調(diào)用順序時的相互作用關(guān)系,只能測試其中一個子集。

圖7-17單元測試過程

10.單元測試過程單元測試過程包括以下環(huán)節(jié):

(1)準(zhǔn)備階段:培訓(xùn)、環(huán)境、工具、測試用例等。

(2)代碼編制階段:編碼、測試用例的修改等。

(3)代碼審查階段:各種語法檢查和算法邏輯等。

(4)單元測試階段:執(zhí)行測試用例,并記錄測試結(jié)果。

(5)評審、提交階段:評審結(jié)論、提交相關(guān)文檔。

11.單元測試內(nèi)容

單元測試內(nèi)容如圖7-18所示。

圖7-18單元測試內(nèi)容

1)模塊接口測試

模塊接口測試是單元測試的基礎(chǔ)。只有在數(shù)據(jù)能正確流入、流出模塊的前提下,其他測試才有意義。

測試接口正確與否應(yīng)該考慮下列因素:

輸入的實際參數(shù)與形式參數(shù)的個數(shù)是否相同;

輸入的實際參數(shù)與形式參數(shù)的屬性是否匹配;

輸入的實際參數(shù)與形式參數(shù)的量綱是否一致;

調(diào)用其他模塊時所給實際參數(shù)的個數(shù)是否與被調(diào)模塊的形參個數(shù)相同;

調(diào)用其他模塊時所給實際參數(shù)的屬性是否與被調(diào)模塊的形參屬性匹配;

調(diào)用其他模塊時所給實際參數(shù)的量綱是否與被調(diào)模塊的形參量綱一致;

調(diào)用預(yù)定義函數(shù)時所用參數(shù)的個數(shù)、屬性和次序是否正確;

是否存在與當(dāng)前入口點無關(guān)的參數(shù)引用;

是否修改了只讀型參數(shù);

各模塊對全程變量的定義是否一致;

是否把某些約束作為參數(shù)傳遞。如果模塊內(nèi)包括外部輸入/輸出,還應(yīng)該考慮下列因素:

文件屬性是否正確;

OPEN/CLOSE語句是否正確;

格式說明與輸入/輸出語句是否匹配;

緩沖區(qū)大小與記錄長度是否匹配;

文件使用前是否已經(jīng)打開;

是否處理了文件尾;

是否處理了輸入/輸出錯誤;

輸出信息中是否有文字性錯誤。

2)局部數(shù)據(jù)結(jié)構(gòu)測試

檢查局部數(shù)據(jù)結(jié)構(gòu)是為了保證臨時存儲在模塊內(nèi)的數(shù)據(jù)在程序執(zhí)行過程中完整、正確。局部數(shù)據(jù)結(jié)構(gòu)往往是錯誤的根源,應(yīng)仔細設(shè)計測試用例,力求發(fā)現(xiàn)以下幾類錯誤:

不合適或不相容的類型說明;

變量無初值;

變量初始化或缺省值有錯;

不正確的變量名(拼錯或不正確地截斷);

出現(xiàn)上溢、下溢和地址異常。

3)獨立路徑測試

在模塊中應(yīng)對每一條獨立執(zhí)行路徑進行測試。此時,設(shè)計測試用例是為了發(fā)現(xiàn)因錯誤計算、不正確的比較和不適當(dāng)?shù)目刂屏髟斐傻腻e誤。獨立路徑測試和循環(huán)測試是最常用且最有效的測試技術(shù)。

4)錯誤處理測試

一個好的設(shè)計應(yīng)能預(yù)見各種出錯條件,并預(yù)設(shè)各種出錯處理通路。出錯處理通路需要認真測試,測試應(yīng)著重檢查下列問題:

輸出的出錯信息是否難以理解;

記錄的錯誤與實際遇到的錯誤是否相符;

在程序自定義的出錯處理運行之前,系統(tǒng)是否已介入;

異常處理是否得當(dāng);

錯誤陳述中是否能提供足夠的定位出錯信息。

5)邊界條件測試邊界條件測試是單元測試中最后也是最重要的一項任務(wù),因為軟件經(jīng)常在邊界上失效。采用邊界值分析技術(shù),針對邊界值及其左右值設(shè)計測試用例,即檢查以下幾種情況:

在n次循環(huán)的第0次、1次、n次是否有錯誤;

運算或判斷中取最大值、最小值時是否有錯誤;

數(shù)據(jù)流、控制流中剛好等于、大于、小于確定的比較值是否出現(xiàn)錯誤。

12.單元測試學(xué)習(xí)中的一些誤區(qū)

(1)很多人認為單元測試?yán)速M了太多的時間。在許多項目設(shè)計過程中,一旦編碼完成,開發(fā)人員總是迫切希望進行軟件的集成工作,因為這樣就能夠很快看到整個系統(tǒng)的工作情況了。因而像單元測試這樣的活動往往不被重視,甚至有時也許會被忽略。然而沒有進行單元測試的系統(tǒng)能夠正常工作的可能性是很小的,因為沒有經(jīng)過單元測試的系統(tǒng)充滿了各式各樣的Bug。在實際軟件開發(fā)過程中,這樣一種忽略單元測試的開發(fā)步驟常常會導(dǎo)致一些嚴(yán)重結(jié)果,如軟件無法運行,將要花費更多的時間去解決模塊中存在的Bug。在單獨模塊的情況下,這些Bug可能是瑣碎和微不足道的,但是在軟件集成為一個系統(tǒng)時這些Bug的影響將被放大,進而使得整個系統(tǒng)無法可靠運行。

(2)根據(jù)單元代碼,確定單元模塊做了什么功能。在實際中,程序員們沒有為每個單元模塊編寫詳細的規(guī)格說明和注釋,當(dāng)需要測試這些沒有規(guī)格說明和注釋的單元模塊時,測試人員往往就會犯一個很大的錯誤:去閱讀這些單元代碼并找出這些單元模塊做了什么樣的功能,即測試人員的測試工作是基于已經(jīng)寫好的代碼基礎(chǔ)之上的,顯然這種測試是沒有任何說服力的,往往也是不會發(fā)現(xiàn)任何Bug的。

正確的測試應(yīng)該是:針對單元模塊應(yīng)該有一個詳細的規(guī)格說明,測試應(yīng)以規(guī)格說明為基礎(chǔ),即對單元模塊的測試是基于它的規(guī)格說明的,而不是基于代碼本身的??墒窃趯嶋H中會出現(xiàn)這樣的情況:一個測試人員要面對的是測試一個沒有規(guī)格說明的單元模塊。這時該怎么做呢?首先通過代碼注釋或是其他途徑了解單元模塊要完成什么功能,然后針對分析出的單元功能去測試代碼是否已經(jīng)完成了這些功能和是否存在Bug。

(3)能力較強的程序員寫出的模塊就可以不進行單元測試。在每個開發(fā)團隊中都存在著一些編程能力較強的程序員,他們非常擅長編程,他們寫的軟件總能在第一時間運行。所以就有很多人認為這些優(yōu)秀程序員編寫的單元模塊就可以不進行單元測試。這樣的理解是完全錯誤的,因為每個人都會犯錯誤。

(4)反正要進行集成測試,單元測試就可以不用做。這個觀點不成立的原因在于規(guī)模越大的代碼集成意味著復(fù)雜度越高。如果軟件的單元模塊沒有事先進行測試,那么開發(fā)人員很可能會花費大量的時間僅僅是為了使軟件能夠運行,而任何實際的測試方案都無法執(zhí)行。

一旦軟件可以運行了,開發(fā)人員又要面對這樣的問題:在考慮軟件全局復(fù)雜性的前提下對每個單元進行全面的測試。這是一件非常困難的事情,甚至在創(chuàng)造一種單元調(diào)用的測試條件的時候,都要全面考慮單元被調(diào)用時的各種入口參數(shù)。在軟件集成階段,對單元功能全面測試的復(fù)雜程度遠遠超過獨立進行的單元測試過程。不進行單元測試的結(jié)果是測試將無法達到它所應(yīng)該有的全面性,一些缺陷將被遺漏,并且很多Bug將被忽略。7.4.2集成測試

1.集成測試的定義

根據(jù)實際情況將程序模塊采用適當(dāng)?shù)募蓽y試策略組裝起來,對系統(tǒng)的接口以及集成后的功能進行正確性檢驗的測試工作就是集成測試,如圖7-19所示。圖7-19集成測試集成測試(也叫組裝測試或聯(lián)合測試)是單元測試的邏輯擴展。它的最簡單的形式是:將兩個已經(jīng)測試過的單元組合成一個組件,并且測試它們之間的接口。從這一層意義上講,組件是指多個單元的集成聚合。在現(xiàn)實方案中,許多單元組合成組件,而這些組件又聚合成程序的更大部分。測試方法是測試片段的組合,并擴展進程,將這個模塊與其他組的模塊一起測試,最后將構(gòu)成進程的所有模塊一起測試。此外,如果程序由多個進程組成,應(yīng)該分別測試它們,而不是同時測試所有進程。

2.集成測試與軟件開發(fā)之間的關(guān)系

從軟件開發(fā)與測試V模型可知,集成測試是和軟件開發(fā)過程中的概要設(shè)計階段相對應(yīng)的。概要設(shè)計的關(guān)于整個系統(tǒng)的體系結(jié)構(gòu)就是集成測試的基礎(chǔ),而集成測試也為軟件架構(gòu)中是否有錯誤和遺漏提供了服務(wù)。兩者是相輔相成的。

為了使讀者更好地了解集成測試與開發(fā)的關(guān)系,圖7-20給出了軟件基本結(jié)構(gòu)圖。

圖7-20軟件基本結(jié)構(gòu)圖

3.集成測試的重點

(1)各個模塊連接起來后,穿過模塊接口的數(shù)據(jù)是否會丟失,是否能夠按期望值傳遞給另外一個模塊。

(2)各個模塊連接起來后,需要判斷是否仍然存在單元測試時未發(fā)現(xiàn)的資源競爭問題。

(3)分別通過單元測試的子功能模塊集成到一起能否實現(xiàn)所期望的父功能。

(4)檢查引入一個模塊后,是否對其他與之相關(guān)的模塊產(chǎn)生負面影響。

(5)全局數(shù)據(jù)結(jié)構(gòu)是否正確,是否被不正常修改。

(6)集成后,每個模塊的誤差是否會累計擴大,是否會達到不可接受的程度。

4.集成測試的層次

對于傳統(tǒng)軟件來說,按集成粒度不同,可以把集成測試分為3個層次,即:

模塊內(nèi)集成測試;

子系統(tǒng)內(nèi)集成測試;

子系統(tǒng)間集成測試。

對于面向?qū)ο髴?yīng)用系統(tǒng)來說,按集成粒度不同,可以把集成測試分為以下兩個層次:

類內(nèi)集成測試;

類間集成測試。

5.如何進行集成測試

(1)體系結(jié)構(gòu)分析。首先跟蹤需求分析,劃分出系統(tǒng)結(jié)構(gòu)層次圖。其次對系統(tǒng)中各個組件之間的依賴關(guān)系進行分析,然后據(jù)此確定集成測試的粒度,即集成模塊的大小。

(2)模塊分析。一般可從以下幾個角度進行模塊分析:

確定本次要測試的模塊;

找出與該模塊相關(guān)的所有模塊,并且按優(yōu)先級對這些模塊進行排列;

從優(yōu)先級最高的相關(guān)模塊開始,把被測模塊與其集成到一起;

依次集成其他模塊。

(3)接口分析。接口的劃分要以概要設(shè)計為基礎(chǔ),一般通過以下幾個步驟來完成:

確定系統(tǒng)的邊界、子系統(tǒng)的邊界和模塊的邊界;

確定模塊內(nèi)部的接口;

確定子系統(tǒng)內(nèi)模塊間接口;

確定子系統(tǒng)間接口;

確定系統(tǒng)與操作系統(tǒng)的接口;

確定系統(tǒng)與硬件的接口;

確定系統(tǒng)與第三方軟件的接口。

(4)風(fēng)險分析。風(fēng)險通常被分為以下三種類型:

項目風(fēng)險:包括項目管理和項目環(huán)境的風(fēng)險。

商業(yè)風(fēng)險:與領(lǐng)域內(nèi)的相關(guān)概念及規(guī)則息息相關(guān)。

技術(shù)風(fēng)險:針對應(yīng)用程序的具體實現(xiàn)而言,主要和代碼級的測試有關(guān)。風(fēng)險分析是一個定義風(fēng)險并且找出阻止?jié)撛诘膯栴}變成現(xiàn)實的方法的過程。通常把風(fēng)險分析分為三個階段:風(fēng)險識別、風(fēng)險評估和風(fēng)險處理。

(5)可測試性分析。必須盡可能早地分析接口的可測試性,提前為后續(xù)的測試工作做好準(zhǔn)備。

(6)集成測試策略分析。集成測試策略分析的主要任務(wù)就是根據(jù)被測對象選擇合適的集成測試策略。

6.集成測試策略

1)非增量式測試(也稱大爆炸集成)

(1)目的。盡可能縮短測試時間,使用最少的測試用例驗證系統(tǒng)。

(2)定義。大爆炸集成也稱為一次性組裝或整體拼裝,這種集成測試的做法就是把所有通過單元測試的模塊一次性集成到一起進行測試,不考慮組件之間的互相依賴性及可能存在的風(fēng)險。

(3)方法。舉例來說,假設(shè)要對某個系統(tǒng)的部分功能(包括四個模塊)進行測試,其功能分解如圖7-21所示。

具體測試過程如下:

①對模塊A進行測試;

②對模塊B進行測試;

③對模塊C和模塊D進行測試;

④把通過單元測試的所有模塊組裝到一起進行集成測試。

圖7-21程序結(jié)構(gòu)圖

圖7-22大爆炸法示例圖

Tests

TestA(withstubsforBandC) //測試模塊A,模塊B和C為樁模塊

TestB(withdriverforAandstubforD) //測試模塊B,A為驅(qū)動模塊,D為樁模塊

TestC(withdriverforA) //測試模塊C,A為驅(qū)動模塊

TestD(withdriverforB) //測試模塊D,B為驅(qū)動模塊

Test(A,B,C,D) //集成測試模塊A、B、C、D

(4)優(yōu)點。

可以并行調(diào)試所有模塊;

需要的測試用例數(shù)目少;

測試方法簡單、易行。

(5)缺點。

不能對各個模塊之間的接口進行充分的測試。

不能很好地對全局數(shù)據(jù)結(jié)構(gòu)進行測試。

如果一次集成的模塊數(shù)量多,集成測試后可能會出現(xiàn)大量的錯誤。另外,修改了一處錯誤之后,很可能新增更多的錯誤,新舊錯誤混雜,給程序的完善帶來很大的麻煩。

即使集成測試通過,也會遺漏很多錯誤。

(6)適用范圍。

只需要修改或增加少數(shù)幾個模塊的前期產(chǎn)品穩(wěn)定的項目。

功能少,模塊數(shù)量不多,程序邏輯簡單,并且每個組件都已經(jīng)過充分單元測試的小型項目。

基于嚴(yán)格的凈室軟件工程(由IBM公司開創(chuàng)的開發(fā)零缺陷或接近零缺陷的軟件的成功做法)開發(fā)的產(chǎn)品,并且在每個開發(fā)階段,產(chǎn)品質(zhì)量和單元測試質(zhì)量都相當(dāng)高的產(chǎn)品。

2)自頂向下集成

(1)目的。從頂層控制(主控模塊)開始,采用同設(shè)計順序一樣的思路對被測系統(tǒng)進行測試,以驗證系統(tǒng)的穩(wěn)定性。

(2)定義。自頂向下的集成測試就是按照系統(tǒng)層次結(jié)構(gòu)圖,以主程序模塊為中心,自上而下地按照深度優(yōu)先或者廣度優(yōu)先策略,對各個模塊一邊組裝一邊進行測試。

(3)方法。集成測試的過程如下:

把主控模塊作為測試驅(qū)動,所有與主控模塊直接相連的模塊作為樁模塊。

根據(jù)集成的方式(深度優(yōu)先或者廣度優(yōu)先),逐漸使用實際模塊替換相應(yīng)的下層樁模塊;再用樁代替它們的直接下屬模塊,與已通過測試的模塊或子系統(tǒng)組裝成新的子系統(tǒng)。在每個模塊被集成時,都必須已經(jīng)通過了單元測試。

進行回歸測試(重新執(zhí)行以前做過的全部或部分測試),以確定集成新模塊后沒有引入錯誤。

從上述過程中的第二步開始重復(fù)執(zhí)行,直到所有模塊都已經(jīng)集成到系統(tǒng)中為止。

按深度優(yōu)先自頂向下集成的示例如圖7-23所示(其程序結(jié)構(gòu)圖如圖7-21所示)。

圖7-23深度優(yōu)先集成過程示意圖

圖7-24廣度優(yōu)先集成過程示意圖

(4)優(yōu)點。

在測試的過程中,可以較早地驗證主要的控制和判斷點。

選擇深度優(yōu)先組合方式,可以首先實現(xiàn)和驗證一個完整的軟件功能,可先對邏輯輸入的分支進行組裝和測試,檢查并克服潛藏的錯誤和缺陷,驗證其功能的正確性,為此后主要分支的組裝和測試提供保證。也能夠較早地驗證功能的可行性,給開發(fā)者和用戶帶來成功的信心。

只有在個別情況下才需要驅(qū)動程序(最多不超過一個),減少了測試驅(qū)動程序的開發(fā)和維護費用。

可以和開發(fā)設(shè)計工作一起并行執(zhí)行集成測試,能夠靈活地適應(yīng)目標(biāo)環(huán)境。

容易進行故障隔離和錯誤定位。

(5)缺點。

在測試時需要為每個模塊的下層模塊提供樁模塊,樁模塊的開發(fā)和維護費用大。

底層組件的需求變更可能會影響全局組件,需要修改整個系統(tǒng)的多個上層模塊。

要求控制模塊具有比較高的可測試性。

可能會導(dǎo)致底層模塊,特別是被重用的模塊測試不夠充分。

(6)適用范圍。

控制結(jié)構(gòu)比較清晰和穩(wěn)定的應(yīng)用程序。

系統(tǒng)高層的模塊接口變化的可能性比較小的應(yīng)用程序。

低層模塊接口還未定義或可能會經(jīng)常因需求變更等原因被修改的應(yīng)用程序。

控制模塊技術(shù)風(fēng)險較大,需要盡可能提前驗證的應(yīng)用程序。

需要盡早看到系統(tǒng)功能行為的應(yīng)用程序。

在極限編程(ExtremeProgramming)中使用測試優(yōu)先的開發(fā)方法。

3)自底向上集成

(1)目的。從依賴性最小的底層模塊開始,按照層次結(jié)構(gòu)圖,逐層向上集成,驗證系統(tǒng)的穩(wěn)定性。其示例如圖7-25所示。

圖7-25自底向上集成示意圖

(2)定義。自底向上集成是從系統(tǒng)層次結(jié)構(gòu)圖的最底層模塊開始進行組裝和集成測試的方式。

(3)方法。

從最底層的模塊開始組裝,組合成一個能夠完成制定的軟件子功能的構(gòu)件;

編制驅(qū)動程序,協(xié)調(diào)測試用例的輸入與輸出;

測試集成后的構(gòu)件;

使用實際模塊代替驅(qū)動程序,按程序結(jié)構(gòu)向上組裝測試后的構(gòu)件;

重復(fù)上面的第二步,直到系統(tǒng)的最頂層模塊被加入到系統(tǒng)中為止。

(4)優(yōu)點。

即使數(shù)據(jù)流并未構(gòu)成有向的非環(huán)狀圖,生成測試數(shù)據(jù)也沒有困難;

可以盡早地驗證底層模塊的行為;

提高了測試效率;

對實際被測模塊的可測試性要求不高;

減少了樁模塊的工作量;

容易對錯誤進行定位。

(5)缺點。

直到最后一個模塊加進去之后才能看到整個系統(tǒng)的框架;

只有到測試過程的后期才能發(fā)現(xiàn)時序問題和資源競爭問題;

驅(qū)動模塊的設(shè)計工作量大;

不能及時發(fā)現(xiàn)高層模塊設(shè)計上的錯誤。

(6)適用范圍。

底層模塊接口比較穩(wěn)定的產(chǎn)品;

高層模塊接口變更比較頻繁的產(chǎn)品;

底層模塊開發(fā)和單元測試工作完成較早的產(chǎn)品。

4)三明治集成

(1)目的。綜合利用自頂向下和自底向上兩種集成測試策略的優(yōu)點。

圖7-26三明治集成策略示意圖

(2)定義。三明治集成是一種混合增值式測試策略,綜合了自頂向下和自底向上兩種集成方法的優(yōu)點,因此也屬于基于功能分解集成。

(3)方法。首先,確定以哪一層為界來決定使用三明治集成策略(在圖7-26中,我們確定以B模塊為界)。其次,對模塊B及其所在層下面的各層使用自底向上的集成策略。再次,對模塊B所在層上面的層次使用自頂向下的集成策略。然后,把模塊B所在層各模塊同相應(yīng)的下層集成。最后,對系統(tǒng)進行整體測試。

(4)優(yōu)點。除了具有自頂向下和自底向上兩種集成策略的優(yōu)點之外,運用一定的技巧,還能夠減少樁模塊和驅(qū)動模塊的開發(fā)量。

(5)缺點。在被集成之前,中間層不能盡早得到充分的測試。

(6)適用范圍。多數(shù)軟件開發(fā)項目都可以應(yīng)用此集成測試策略。

7.集成測試過程

根據(jù)集成測試不同階段的任務(wù),可以把集成測試劃分為五個階段:計劃階段、設(shè)計階段、實施階段、執(zhí)行階段、評估階段,如圖7-27所示。

圖7-27集成測試過程

(1)計劃階段。一般安排在概要設(shè)計評審?fù)ㄟ^后大約一個星期的時候,參考需求規(guī)格說明書、概要設(shè)計文檔、產(chǎn)品開發(fā)、計劃時間表來制定。

(2)設(shè)計階段。一般在詳細設(shè)計開始時就可以著手進行??梢园研枨笠?guī)格說明書、概要設(shè)計、集成測試計劃文檔作為參考依據(jù)。

(3)實施階段。在實施的過程中,我們要參考需求規(guī)格說明書、概要設(shè)計、集成測試計劃、集成測試設(shè)計等相關(guān)文檔來進行。

(4)執(zhí)行階段。只要所有的集成測試工作準(zhǔn)備完畢,測試人員在單元測試完成以后就可以執(zhí)行集成測試。

(5)評估階段。當(dāng)集成測試執(zhí)行結(jié)束后,要召集相關(guān)人員對測試結(jié)果進行評估,確定軟件是否通過集成測試。

8.集成測試環(huán)境

在搭建集成測試環(huán)境時,可以從以下幾個方面進行考慮:

硬件環(huán)境;

操作系統(tǒng)環(huán)境;

數(shù)據(jù)庫環(huán)境;

網(wǎng)絡(luò)環(huán)境;

測試工具運行環(huán)境;

其他環(huán)境。

9.集成測試用例設(shè)計

(1)為系統(tǒng)運行設(shè)計用例??墒褂玫闹饕獪y試分析技術(shù)包括:

等價類劃分法;

邊界值分析法;

基于決策表的測試。

(2)為正向測試設(shè)計用例。正向集成測試的一個重點就是驗證這些集成后的模塊是否實現(xiàn)了預(yù)期的功能。基于這樣的測試目標(biāo),我們可以直接根據(jù)概要設(shè)計文檔導(dǎo)出相關(guān)的用例??墒褂萌缦聨追N主要測試分析技術(shù):

輸入域測試;

輸出域測試;

等價類劃分;

狀態(tài)轉(zhuǎn)換測試;

規(guī)范導(dǎo)出法。

在集成測試中的逆向測試包括分析被測接口是否實現(xiàn)了需求規(guī)格沒有描述的功能,檢查規(guī)格說明中可能出現(xiàn)的接口遺漏或者判斷接口定義是否有錯誤,以及可能出現(xiàn)的接口異常錯誤,包括接口數(shù)據(jù)本身的錯誤、接口數(shù)據(jù)順序錯誤等??墒褂孟旅鎺追N主要測試分析技術(shù):

錯誤猜測法;

基于風(fēng)險的測試;

基于故障的測試;

邊界值分析;

特殊值測試;

狀態(tài)轉(zhuǎn)換測試。

(3)為滿足特殊需求設(shè)計用例。在大部分軟件產(chǎn)品的開發(fā)過程中,模塊設(shè)計文檔已經(jīng)明確地指出了接口要達到的安全性指標(biāo)、性能指標(biāo)等。因此應(yīng)該在對模塊進行單元測試和集成測試階段就測試這些特殊需求是否達到,為整個系統(tǒng)是否能夠滿足這些特殊需求把關(guān)??墒褂玫闹饕獪y試分析技術(shù)是規(guī)范導(dǎo)出法。

(4)為高覆蓋設(shè)計用例。與單元測試所關(guān)注的覆蓋重點不同,在集成測試階段我們關(guān)注的主要覆蓋是功能覆蓋和接口覆蓋,通過對集成后的模塊進行分析,來判斷哪些功能以及哪些接口沒有被覆蓋到,并以此設(shè)計測試用例。可使用以下兩種主要測試分析技術(shù):

功能覆蓋分析;

接口覆蓋分析。

(5)測試用例補充。在軟件開發(fā)的過程中,難免會因為需求變更等原因,而有功能增加、特性修改等情況發(fā)生。因此,我們不可能在測試工作的一開始就100%完成所有的集成測試用例的設(shè)計,這就需要在集成測試階段能夠及時跟蹤項目變化,按照需求增加和補充集成測試用例,保證進行充分的集成測試。

(6)注意事項。在集成測試的過程中,要注意考慮軟件開發(fā)成本、進度和質(zhì)量這三個方面的平衡。不能顧此失彼,也就是說要重點突出(在有限的時間內(nèi)進行窮盡的測試是不可能的)。

10.集成測試與系統(tǒng)測試的區(qū)別

(1)測試對象:集成測試的測試對象是由通過了單元測試的各個模塊所集成起來的組件;而系統(tǒng)測試的測試對象,除了軟件之外,還有計算機硬件及相關(guān)的外圍設(shè)備、數(shù)據(jù)采集和傳輸機構(gòu)、計算機系統(tǒng)操作人員等的整個系統(tǒng)。

(2)測試時間:集成測試是介于單元測試和系統(tǒng)測試之間的測試,在測試時間上先于系統(tǒng)測試。

(3)測試方法:集成測試通常會采用灰盒測試,而系統(tǒng)測試通常使用黑盒測試。

(4)測試內(nèi)容:集成測試的主要內(nèi)容是各個單元模塊之間的接口,以及各個模塊集成后所實現(xiàn)的功能;而系統(tǒng)測試的主要內(nèi)容是整個系統(tǒng)的功能和性能。

(5)測試目的:集成測試的主要目的是發(fā)現(xiàn)單元之間接口的錯誤以及集成后的軟件同軟件概要設(shè)計說明不一致的地方;而系統(tǒng)測試的主要目的是通過與系統(tǒng)需求定義相比較之后發(fā)現(xiàn)軟件與系統(tǒng)定義不符合或矛盾的地方。

(6)測試角度:集成測試工作的開展更多的是站在測試工作人員的角度上,而系統(tǒng)測試工作的開展更多的是站在用戶的角度來進行。

11.集成測試經(jīng)驗總結(jié)

集成測試界于單元測試和系統(tǒng)測試之間,不易正確理解和把握。因此,有些項目在開發(fā)過程中使用調(diào)試的手段把模塊或子系統(tǒng)一個一個地集成起來,并用這種辦法來替換集成測試,而忽略了正規(guī)的集成測試,致使軟件中存在很多隱患,因而無法保證質(zhì)量。

根據(jù)以往項目開發(fā)和測試的實踐,總結(jié)了如下幾條集成測試的經(jīng)驗:

(1)根據(jù)概要設(shè)計盡早進行集成測試計劃。

(2)要根據(jù)項目的實際情況制定一些覆蓋率標(biāo)準(zhǔn),從而根據(jù)覆蓋率標(biāo)準(zhǔn)來設(shè)計足夠多的測試用例,然后通過覆蓋率分析來衡量集成測試的充分性,補充測試用例,最終使軟件質(zhì)量得到保證。

(3)在選擇集成測試策略時,應(yīng)當(dāng)綜合考慮軟件質(zhì)量、開發(fā)成本和開發(fā)進度這三個因素之間的關(guān)系。

(4)要根據(jù)軟件的體系結(jié)構(gòu)特點來選取集成測試策略,盡可能減少樁模塊和驅(qū)動模塊開發(fā)的工作量,同時還要兼顧是否容易進行軟件缺陷定位。

(5)在測試時,可以根據(jù)各種集成測試策略的特點把各種集成測試策略結(jié)合起來。

(6)在進行模塊和接口劃分時,盡量與開發(fā)人員多溝通。

(7)當(dāng)因為需求變更或其他原因更改代碼時,應(yīng)對有改動的模塊及與其關(guān)聯(lián)的模塊進行回歸測試。

(8)從集成測試所使用的測試技術(shù)角度來說,可以使用黑盒測試。經(jīng)過覆蓋率分析后,可以針對沒有覆蓋的代碼或路徑補充一些白盒測試用例。

(9)在必要的時候,例如單獨的手工測試無法完成時,可以選用一些適當(dāng)?shù)募蓽y試工具。

(10)對容易出錯的模塊要進行充分的集成測試。7.4.3確認測試

確認測試又稱有效性測試。有效性測試是在模擬的環(huán)境下,運用黑盒測試的方法,驗證被測軟件是否滿足需求規(guī)格說明書列出的需求。其任務(wù)是驗證軟件的功能和性能及其他特性是否與用戶的要求一致。對軟件的功能和性能要求在軟件需求規(guī)格說明書中已經(jīng)明確規(guī)定,它包含的信息就是軟件確認測試的基礎(chǔ)。

通過集成測試之后,軟件已完全組裝起來,接口方面的錯誤也已排除,確認測試即可開始。確認測試應(yīng)檢查軟件能否按合同要求進行工作,即是否滿足軟件需求說明書中的確認標(biāo)準(zhǔn)。

1.確認測試的范圍

確認測試的范圍與集成測試類似,但并不完全按照集成測試內(nèi)容進行。它們的不同之處在于:

(1)某些已經(jīng)測試過的純粹技術(shù)性的特點可能不需要再次測試。

(2)對用戶特別感興趣的功能或性能,可能需要增加一些測試方案。

(3)主要使用生產(chǎn)中的實際數(shù)據(jù)進行測試。

(4)可能需要設(shè)計并執(zhí)行一些與用戶使用步驟有關(guān)的測試。確認測試必須有用戶參加,或以用戶為主進行。用戶應(yīng)該參加測試方案設(shè)計,分析并評價測試的輸出結(jié)果。為了使用戶能夠積極主動地參與確認測試,特別是用戶能有效地使用這個系統(tǒng),通常在驗收之前應(yīng)由開發(fā)部門對用戶進行培訓(xùn)。

確認測試一般使用黑盒法。測試計劃包括要進行的測試種類和進度安排、測試過程及用來檢驗軟件是否與需求一致的測試方案。通過確認測試要保證軟件能夠滿足所有功能要求、性能要求及其他預(yù)定的要求(如可移植性、兼容性和可維護性等),文檔資料準(zhǔn)確而齊全。如果確認測試發(fā)現(xiàn)軟件的功能或性能與用戶的要求有差距,往往是需求分析階段有差錯。此時的問題涉及面廣,一般解決起來也很困難。為了解決確認測試過程中發(fā)現(xiàn)的軟件錯誤,通常需要和用戶充分協(xié)商。

2.軟件配置復(fù)查

軟件配置復(fù)查是確認過程的一個重要環(huán)節(jié)。其目的是保證軟件配置的所有成分都齊全,各方面的質(zhì)量都符合要求,文檔要與程序一致,具有維護階段所必需的細節(jié),而且已經(jīng)編排好目錄。這些文檔資料包括:用戶資料(例如用戶手冊、操作手冊等)、設(shè)計資料(例如設(shè)計說明書等)、源程序以及測試資料(例如測試說明書、測試報告等)。

除了按合同規(guī)定的內(nèi)容和要求由人工審查軟件配置之外,在確認測試的過程中應(yīng)該嚴(yán)格遵循用戶指南以及其他操作程序,以便檢驗這些使用手冊的完整性和正確性。必須仔細記錄發(fā)現(xiàn)的遺漏或錯誤,并且適當(dāng)?shù)剡M行補充和更正。7.4.4系統(tǒng)測試

1.定義

系統(tǒng)測試是將已經(jīng)確認的軟件、計算機硬件、外設(shè)、網(wǎng)絡(luò)等其他元素結(jié)合在一起,進行信息系統(tǒng)的各種組裝測試和確認測試。其目的是通過與系統(tǒng)的需求相比較,發(fā)現(xiàn)所開發(fā)的系統(tǒng)與用戶需求不符或矛盾的地方,從而提出更加完善的方案。其任務(wù)是盡可能徹底地檢查出程序中的錯誤,提高軟件系統(tǒng)的可靠性,并檢驗系統(tǒng)“做得怎么樣”。系統(tǒng)測試是針對整個產(chǎn)品系統(tǒng)進行的測試,測試的對象不僅僅包括需要測試的產(chǎn)品系統(tǒng)的軟件,還要包含軟件所依賴的硬件、外設(shè)甚至包括某些數(shù)據(jù)、支持軟件及其接口等。因此,必須將系統(tǒng)中的軟件與各種依賴的資源結(jié)合起來,在系統(tǒng)實際運行環(huán)境下進行測試。

系統(tǒng)測試的根本任務(wù)就是要證明被測系統(tǒng)的功能和結(jié)構(gòu)的穩(wěn)定性,系統(tǒng)測試中還包括一些非功能測試,如性能測試、壓力測試、可靠性測試等。系統(tǒng)測試的最終目的是為了確保軟件產(chǎn)品能夠被用戶或操作者接受。測試的主要目標(biāo)不再是找出缺陷,而是證明其性能。系統(tǒng)測試屬于黑盒測試范疇,不再對軟件的源代碼進行分析和測試。

2.系統(tǒng)測試的角色和職責(zé)

軟件測試工程師:制定系統(tǒng)測試計劃和方案并組織評審,按照系統(tǒng)測試方案設(shè)計測試用例和測試代碼,設(shè)計所需測試工具,編寫測試規(guī)程,執(zhí)行系統(tǒng)測試用例,提交并跟蹤缺陷,完成系統(tǒng)測試報告并組織評審,輸出測試案例和總結(jié)等經(jīng)驗文檔。

在系統(tǒng)測試過程中還可能涉及的主要角色包括:

(1)系統(tǒng)分析設(shè)計人員:提出系統(tǒng)測試需求,進行測試需求跟蹤及軟件系統(tǒng)可測性分析,確定系統(tǒng)測試的對象、范圍和方法。

(2)開發(fā)人員:需要參與系統(tǒng)測試計劃和方案的評審,跟蹤解決軟件測試人員發(fā)現(xiàn)的缺陷,評審系統(tǒng)測試報告。

(3)配置管理人員:對系統(tǒng)測試文檔進行配置管理。

(4)質(zhì)量保證人員:對系統(tǒng)測試過程進行審計。

3.系統(tǒng)測試過程

系統(tǒng)測試過程要經(jīng)歷五個階段,如圖7-28所示。

圖7-28系統(tǒng)測試過程

(1)計劃階段:制定測試計劃。

(2)設(shè)計階段:對系統(tǒng)進行詳細的測試分析,然后設(shè)計一些典型的、滿足測試需求的測試用例,同時給出系統(tǒng)測試的大致過程。

(3)實施階

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論