您的位置:軟件測(cè)試 > 開(kāi)源軟件測(cè)試 > 開(kāi)源單元測(cè)試工具 > junit
追求代碼質(zhì)量: 用 JUnitPerf 進(jìn)行性能測(cè)試
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2012/12/7 11:43:02 ] 推薦標(biāo)簽:

    在應(yīng)用程序的開(kāi)發(fā)周期中,性能測(cè)試常被放到后考慮,這并不是因?yàn)樗恢匾,而是因(yàn)榇嬖谶@么多未知變量,很難有效地測(cè)試。在本月的 追求代碼質(zhì)量 系列中,Andrew Glover 使性能測(cè)試成為開(kāi)發(fā)周期的一部分,并介紹了兩種簡(jiǎn)單的實(shí)現(xiàn)方法。

在應(yīng)用程序的開(kāi)發(fā)中,驗(yàn)證應(yīng)用程序的性能幾乎總處于次要的地位。請(qǐng)注意,我強(qiáng)調(diào)的是驗(yàn)證 應(yīng)用程序的性能。應(yīng)用程序的性能總是 首要考慮的因素,但開(kāi)發(fā)周期中卻很少包含對(duì)性能的驗(yàn)證。

由于種種原因,性能測(cè)試常被延遲到開(kāi)發(fā)周期的后期。以我的經(jīng)驗(yàn),企業(yè)之所以在開(kāi)發(fā)過(guò)程中不包含性能測(cè)試是因?yàn)椋麄儾恢缹?duì)于正在進(jìn)行開(kāi)發(fā)的應(yīng)用程序要期待什么。提出了一些(性能)指數(shù),但這些指數(shù)是基于預(yù)期負(fù)載提出的。

發(fā)生下列兩種情況之一時(shí),性能測(cè)試成為頭等大事:

    生產(chǎn)中出現(xiàn)顯而易見(jiàn)的性能問(wèn)題。
    在同意付費(fèi)之前 ,客戶或潛在客戶詢問(wèn)有關(guān)性能指數(shù)的問(wèn)題。

本月,我將介紹兩種簡(jiǎn)單的性能測(cè)試技術(shù),在上述兩種情況中的任何一種發(fā)生前進(jìn)行測(cè)試。

用 JUnitPerf 進(jìn)行測(cè)試

在軟件開(kāi)發(fā)的早期階段,使用 JUnit 很容易確定基本的低端性能指數(shù)。JUnitPerf 框架能夠?qū)y(cè)試快速地轉(zhuǎn)化為簡(jiǎn)單的負(fù)載測(cè)試,甚至壓力測(cè)試。

可使用 JUnitPerf 創(chuàng)建兩種測(cè)試類型:TimedTest 和 LoadTest。這兩種類型都基于 Decorator 設(shè)計(jì)模式并利用 JUnit 的 suite 機(jī)制。TimedTest 為測(cè)試樣例創(chuàng)建一個(gè)(時(shí)間)上限 —— 如果超過(guò)這個(gè)時(shí)間,那么測(cè)試失敗。LoadTest 和計(jì)時(shí)器一起運(yùn)行,它通過(guò)運(yùn)行所需的次數(shù)(時(shí)間間隔由配置的計(jì)時(shí)器控制),在一個(gè)特定的測(cè)試用例上創(chuàng)建一個(gè)人工負(fù)載。

恰當(dāng)?shù)臅r(shí)限測(cè)試

JUnitPerf TimedTest 讓您可以編寫(xiě)有相關(guān)時(shí)間限制的測(cè)試 —— 如果超過(guò)了該限度,認(rèn)為測(cè)試是失敗的(即便測(cè)試邏輯本身實(shí)際上是成功的)。在測(cè)試對(duì)于業(yè)務(wù)致關(guān)重要的方法時(shí),時(shí)限測(cè)試相比其他測(cè)試來(lái)說(shuō),在確定和監(jiān)控性能指數(shù)方面很有幫助。甚至可以測(cè)試得更加細(xì)致一些,可以測(cè)試一系列方法來(lái)確保它們滿足特定的時(shí)間限制。

例如,假設(shè)存在一個(gè) Widget 應(yīng)用程序,其中,特定的對(duì)于業(yè)務(wù)致關(guān)重要的方法(如 createWidget())是嚴(yán)格的性能限制的測(cè)試目標(biāo)。假設(shè)需要對(duì)執(zhí)行該 create() 方法的功能方面進(jìn)行性能測(cè)試。這通常會(huì)由不同的團(tuán)隊(duì)使用不同的工具在開(kāi)發(fā)周期的后期加以確定,這通常不能指出精確的方法。但假設(shè)決定選擇早期經(jīng)常測(cè)試 方法取而代之。

創(chuàng)建 TimedTest 首先要?jiǎng)?chuàng)建一個(gè)標(biāo)準(zhǔn)的 JUnit 測(cè)試。換言之,將對(duì) TestCase 或其派生類進(jìn)行擴(kuò)展,并編寫(xiě)一個(gè)以 test 開(kāi)頭的方法,如清單 1 所示:


清單 1. 簡(jiǎn)單的 widget 測(cè)試

public class WidgetDAOImplTest extends TestCase { 
 private WidgetDAO dao;

 public void testCreate() throws Exception{
  IWidget wdgt = new Widget();
  wdgt.setWidgetId(1000);
  wdgt.setPartNumber("12-34-BBD"); 
  try{
   this.dao.createWidget(wdgt);
  }catch(CreateException e){
   TestCase.fail("CreateException thrown creating a Widget");
  }    
 }

 protected void setUp() throws Exception {      
  ApplicationContext context =
   new ClassPathXmlApplicationContext("spring-config.xml");     
  this.dao = (WidgetDAO) context.getBean("widgetDAO");     
 }    
}
 


由于 JUnitPerf 是一個(gè)基于裝飾器的框架,為了真正地駕馭它,必須提供一個(gè) suite() 方法并將現(xiàn)有的測(cè)試裝飾以 TimedTest。TimedTest 以 Test 和執(zhí)行該測(cè)試的大時(shí)間量作為參數(shù)。

也可以選擇傳入一個(gè) boolean 標(biāo)志作為第三個(gè)參數(shù)(false),這將導(dǎo)致測(cè)試快速失敗 —— 意味著如果超過(guò)大時(shí)間,JUnitPerf 將立即 迫使測(cè)試失敗。否則,測(cè)試樣例將完整運(yùn)行,然后失敗。區(qū)別很微妙:在一個(gè)失敗的樣例中,不帶可選標(biāo)志運(yùn)行測(cè)試可以幫您了解運(yùn)行總時(shí)間。傳入 false 值卻意味著得不到運(yùn)行總時(shí)間。

例如,在清單 2 中,我在運(yùn)行 testCreate() 時(shí)設(shè)定了一個(gè)兩秒鐘的上限。如果執(zhí)行總時(shí)間超過(guò)了這個(gè)時(shí)間,測(cè)試樣例將失敗。由于我并未傳入可選的 boolean 參數(shù),該測(cè)試將完整運(yùn)行,而不管運(yùn)行會(huì)持續(xù)多久。


清單 2. 為生成 TimedTest 而實(shí)現(xiàn)的 suite 方法

public static Test suite() {
 long maxElapsedTime = 2000; //2 seconds
 Test timedTest = new TimedTest(
   new WidgetDAOImplTest("testCreate"), maxElapsedTime);
 return timedTest;       
}
 


此測(cè)試通常在 JUnit 框架中運(yùn)行 —— 現(xiàn)有的 Ant 任務(wù)、Eclipse 運(yùn)行器等等,會(huì)像運(yùn)行任何其他 JUnit 測(cè)試一樣運(yùn)行這個(gè)測(cè)試。惟一的不同是,該測(cè)試將發(fā)生在計(jì)時(shí)器的上下文中。

過(guò)度的負(fù)載測(cè)試

與在測(cè)試場(chǎng)景中驗(yàn)證一個(gè)方法(或系列方法)的時(shí)間限制正好相反,JUnitPerf 也方便了負(fù)載測(cè)試。正如在 TimedTest 中一樣,JUnitPerf 的 LoadTest 也像裝飾器一樣運(yùn)行,它通過(guò)將 JUnit Test 和額外的線程信息綁定起來(lái),從而模擬負(fù)載。

使用 LoadTest,可以指定要模擬的用戶(線程)數(shù)量,甚至為這些線程的啟動(dòng)提供計(jì)時(shí)機(jī)制。JUnitPerf 提供兩類 Timer:ConstantTimer 和 RandomTimer。通過(guò)為 LoadTest 提供這兩類計(jì)時(shí)器,可以更真實(shí)地模擬用戶負(fù)載。如果沒(méi)有 Timer,所有線程都會(huì)同時(shí)啟動(dòng)。

清單 3 是用 ConstantTimer 實(shí)現(xiàn)的含 10 個(gè)模擬用戶的負(fù)載測(cè)試:


清單 3. 為生成負(fù)載測(cè)試而實(shí)現(xiàn)的 suite 方法

public static Test suite() {
 int users = 10;
 Timer timer = new ConstantTimer(100);  
 return new LoadTest(
  new WidgetDAOImplTest("testCreate"),
    users, timer);  
}
 


請(qǐng)注意,testCreate() 方法運(yùn)行 10 次,每個(gè)線程間隔 100 毫秒啟動(dòng)。未設(shè)定時(shí)間限制 —— 這些方法完整運(yùn)行,如果其中任何的方法執(zhí)行失敗,JUnit 會(huì)相應(yīng)地報(bào)告失敗。

用樣式進(jìn)行裝飾

裝飾器并不局限于單個(gè)的裝飾物。例如,在 Java™ I/O 中,可以為 FileInputStream 裝飾上一個(gè)帶 BufferedReader 的 InputStreamReader(只要記。築ufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("infilename"), "UTF8")))。

裝飾可以有多個(gè)層次,JUnitPerf 的 TimedTest 和 LoadTest 也是一樣。當(dāng)這兩個(gè)類彼此裝飾時(shí),將導(dǎo)致一些強(qiáng)制的測(cè)試場(chǎng)景,例如像這樣的場(chǎng)景:在一項(xiàng)業(yè)務(wù)中放置了負(fù)載并應(yīng)用了時(shí)間限制;蛘撸覀兛梢詢H僅將之前的兩個(gè)測(cè)試場(chǎng)景以如下方式結(jié)合起來(lái):

    在 testCreate() 方法中放置一項(xiàng)負(fù)載。
    規(guī)定每個(gè)線程必須在該時(shí)間限制內(nèi)結(jié)束。

上一頁(yè)12下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd