乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      追求代碼質(zhì)量: 用 JUnitPerf 進(jìn)行性能測(cè)試

       bananarlily 2014-05-22

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

      由于種種原因,性能測(cè)試常被延遲到開發(fā)周期的后期。以我的經(jīng)驗(yàn),企業(yè)之所以在開發(fā)過(guò)程中不包含性能測(cè)試是因?yàn)椋麄儾恢缹?duì)于正在進(jìn)行開發(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è)試。

      改進(jìn)代碼質(zhì)量

      別錯(cuò)過(guò) Andrew 的 討論論壇,里面有關(guān)于代碼語(yǔ)法、測(cè)試框架以及如何編寫專注于質(zhì)量的代碼的幫助。

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

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

      可使用 JUnitPerf 創(chuàng)建兩種測(cè)試類型:TimedTestLoadTest。這兩種類型都基于 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ù)載。

      回頁(yè)首

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

      JUnitPerf TimedTest 讓您可以編寫有相關(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ì)使用不同的工具在開發(fā)周期的后期加以確定,這通常不能指出精確的方法。但假設(shè)決定選擇早期經(jīng)常測(cè)試 方法取而代之。

      創(chuàng)建 TimedTest 首先要?jiǎng)?chuàng)建一個(gè)標(biāo)準(zhǔn)的 JUnit 測(cè)試。換言之,將對(duì) TestCase 或其派生類進(jìn)行擴(kuò)展,并編寫一個(gè)以 test 開頭的方法,如清單 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è)試裝飾以 TimedTestTimedTestTest 和執(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í)器的上下文中。

      回頁(yè)首

      過(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 提供兩類 TimerConstantTimerRandomTimer。通過(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)告失敗。

      回頁(yè)首

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

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

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

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

      我通過(guò)為一個(gè)標(biāo)準(zhǔn) Test 裝飾上 LoadTest(由 TimedTest 裝飾)應(yīng)用了上述規(guī)范,清單 4 顯示了其結(jié)果。

      清單 4. 經(jīng)裝飾的負(fù)載和時(shí)限測(cè)試
      public static Test suite() {
       int users = 10;
       Timer timer = new ConstantTimer(100);
       long maxElapsedTime = 2000; 	 
       return new TimedTest(new LoadTest(
         new WidgetDAOImplTest("testCreate"), users, timer), 
           maxElapsedTime);  		
      }

      正如您所看到的那樣,testCreate() 方法運(yùn)行 10 次(每隔 100 毫秒啟動(dòng)一個(gè)線程),且每個(gè)線程必須在 2 秒內(nèi)完成,否則整個(gè)測(cè)試場(chǎng)景將失敗。

      回頁(yè)首

      使用注意

      盡管 JUnitPerf 是一個(gè)性能測(cè)試框架,但也要先大致估計(jì)一下測(cè)試要設(shè)定的性能指數(shù)。這是由于所有由 JUnitPerf 裝飾的測(cè)試都通過(guò) JUnit 框架運(yùn)行,所以就存在額外的消耗,特別是在利用 fixture 時(shí)。由于 JUnit 本身用一個(gè) setUp 和一個(gè) tearDown() 方法裝飾所有測(cè)試樣例,所以要在測(cè)試場(chǎng)景的整個(gè)上下文中考慮執(zhí)行時(shí)間。

      相應(yīng)地,我經(jīng)常創(chuàng)建使用我想要的 fixture 邏輯的測(cè)試,但也會(huì)運(yùn)行一個(gè)空白測(cè)試來(lái)確定性能指數(shù)基線。這是一個(gè)大致的估計(jì),但它必須作為基線添加到任何想要的測(cè)試限制中。

      例如,如果運(yùn)行一個(gè)由 fixture 邏輯(使用 DbUnit)裝飾的空白測(cè)試用時(shí) 2.5 秒,那么您想要的所有測(cè)試限制都應(yīng)將這一額外時(shí)間考慮在內(nèi) —— 這可以從清單 5 中的基準(zhǔn)測(cè)試中看到:

      清單 5. JUnitPerf 基準(zhǔn)測(cè)試
      public class DBUnitSetUpBenchmarkTest extends DatabaseTestCase {
       private WidgetDAO dao = null;
      
       public void testNothing(){
        //should be about 2.5 seconds
       }
      
       protected IDatabaseConnection getConnection() throws Exception {        
        Class driverClass = Class.forName("org.hsqldb.jdbcDriver");
        Connection jdbcConnection = 
         DriverManager.getConnection(
           "jdbc:hsqldb:hsql://127.0.0.1", "sa", "");
        return new DatabaseConnection(jdbcConnection);
       }
      
       protected IDataSet getDataSet() throws Exception {        
        return new FlatXmlDataSet(new File("test/conf/seed.xml"));
       }
      
       protected void setUp() throws Exception {
        super.setUp();      
        final ApplicationContext context = 
         new ClassPathXmlApplicationContext("spring-config.xml");      
        this.dao = (WidgetDAO) context.getBean("widgetDAO");      
       }
      }

      請(qǐng)注意,清單 5 的測(cè)試樣例 testNothing()什么都沒(méi)做。其惟一的目的是確定運(yùn)行 setUp() 方法(當(dāng)然,該方法也通過(guò) DbUnit 設(shè)置了一個(gè)數(shù)據(jù)庫(kù))的總時(shí)間。

      也請(qǐng)記住,測(cè)試時(shí)間將依賴于機(jī)器的配置而變化,同時(shí)也依賴于在執(zhí)行 JUnitPerf 測(cè)試時(shí)運(yùn)行的東西而變化。我經(jīng)常發(fā)現(xiàn),將 JUnitPerf 測(cè)試放到它們自己的分類中有助于將它們同標(biāo)準(zhǔn)測(cè)試隔離開。這意味著,在運(yùn)行一個(gè)測(cè)試時(shí)不必每次都運(yùn)行 JUnitPerf 測(cè)試,例如在一個(gè) CI 環(huán)境中簽入代碼。我也會(huì)創(chuàng)建特定的 Ant 任務(wù),從而只在精心策劃的將性能測(cè)試考慮在內(nèi)的場(chǎng)景或環(huán)境中運(yùn)行這些測(cè)試。

      回頁(yè)首

      試試吧!

      用 JUnitPerf 進(jìn)行性能測(cè)試無(wú)疑是一門嚴(yán)格的科學(xué),但在開發(fā)生命周期的早期,這是確定和監(jiān)控應(yīng)用程序代碼的低端性能的極佳方式。另外,由于它是一個(gè)基于裝飾器的 JUnit 擴(kuò)展框架,所以可以很容易地用 JUnitPerf 裝飾現(xiàn)有的 JUnit 測(cè)試。

      想想您已經(jīng)花了這么多時(shí)間來(lái)?yè)?dān)心應(yīng)用程序在負(fù)載下會(huì)怎樣執(zhí)行。用 JUnitPerf 進(jìn)行性能測(cè)試可以為您減少擔(dān)憂并節(jié)省時(shí)間,同時(shí)也確保了應(yīng)用程序代碼的質(zhì)量。

      參考資料

      學(xué)習(xí)

      • 您可以參閱本文在 developerWorks 全球站點(diǎn)上的 英文原文 。
      • Java 理論與實(shí)踐: 用動(dòng)態(tài)代理進(jìn)行修飾”(Brian Goetz,developerWorks,2005 年 8 月):動(dòng)態(tài)代理是構(gòu)建裝飾器和適配器的便利工具。
      • 可重復(fù)的系統(tǒng)測(cè)試”(Andrew Glover,developerWorks,2006 年 9 月):Andrew Glover 介紹了 Cargo,這是一個(gè)開放源碼框架,該框架以一種通用的風(fēng)格對(duì)容器管理進(jìn)行自動(dòng)化。
      • Continuous Performance Testing With JUnitPerf”(Mike Clark,devnewz,2003 年 7 月):Mike Clark 介紹了一種讓您更加自信并減輕壓力的方法,即編寫自動(dòng)化的性能測(cè)試,因?yàn)檫@些測(cè)試是不會(huì)說(shuō)謊的。
      • Effective Unit Testing with DbUnit”(Andrew Glover,OnJava,2004 年 1 月):介紹了用 DbUnit 進(jìn)行的數(shù)據(jù)庫(kù)依賴性測(cè)試。
      • Groovy performance testing():了解如何將 JUnitPerf 和用 Groovy 編寫的測(cè)試結(jié)合使用。
      • 追求代碼質(zhì)量 系列(Andrew Glover,developerWorks):獲得更多有關(guān)代碼語(yǔ)法、測(cè)試框架以及編寫專注于質(zhì)量的代碼的信息。
      • Java 技術(shù)專區(qū):數(shù)百篇關(guān)于 Java 編程各個(gè)方面的文章。

      獲得產(chǎn)品和技術(shù)

      • 下載 JUnit:了解 JUnit 4 的新特性。
      • 下載 JUnitPerf:一系列用于測(cè)量性能和可伸縮性的 JUnit 測(cè)試裝飾器。

      討論

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多