qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

          單元性能測試之使用JUnitPerf測試多線程并發(fā)

          簡介:

            單元測試性能測試在測試領(lǐng)域?qū)儆谝笙鄬^高的測試活動(dòng),也是測試工程師成長、向上發(fā)展的反向。單元測試評(píng)測我們的代碼實(shí)現(xiàn)功能的情況,性能測試則企圖分析應(yīng)用程序的性能表現(xiàn)和負(fù)載能力。那么“單元性能測試”能做什么?我們可以這樣說,單元性能測試以單元測試的形式對代碼進(jìn)行性能測試。單元性能測試像單元測試一樣,需要測試人員編寫測試代碼,但現(xiàn)在關(guān)注的不是代碼的功能實(shí)現(xiàn)情況了,而是想得到被測試代碼的性能數(shù)據(jù),包括執(zhí)行方法耗時(shí)、多線程并發(fā)是否線程安全、內(nèi)存是否泄漏、是否存在短期循環(huán)對象等。單元性能測試相對于系統(tǒng)性能測試更容易定位問題,對關(guān)鍵的方法進(jìn)行測試,可以降低系統(tǒng)性能風(fēng)險(xiǎn),減少系統(tǒng)集成后系統(tǒng)性能測試的工作量。本篇文檔演示如何使用JUnitPerf程序包對代碼進(jìn)行多線程并發(fā)測試。

            待測代碼DateUtil:

            我們待測的程序代碼為com.loggingselenium.DateUtil類。這個(gè)類中有一個(gè)私有靜態(tài)成員timeFormator和一個(gè)靜態(tài)方法compareDateTime(String dateTime1, String dateTime2)。

          package com.loggingselenium;
          import java.util.Date;
          import java.text.SimpleDateFormat;
          public class DateUtil {
           private  static SimpleDateFormat timeFormator =
            new SimpleDateFormat("yyyyMMdd HH:mm:ss");
           public synchronized static int compareDateTime(String dateTime1, String dateTime2) {
            try {
             Date date1 = timeFormator.parse(dateTime1);
             Date date2 = timeFormator.parse(dateTime2);
             if (date1.before(date2))
              return -1;
             if (date1.after(date2))
              return 1;
             else
              return 0;
            } catch (Exception e) {
             throw new RuntimeException("解析日期時(shí)間格式出錯(cuò),期望的字符串格式為[yyyyMMdd HH:mm:ss]");
            }
           }
          }

            單元測試代碼UnitTestDateUtil:

            我們的測試代碼com.loggingselenium.UnitTestDateUtil如下:

          package com.loggingselenium;
          import junit.framework.TestCase;
          public class UnitTestDateUtil extends TestCase {
           protected void setUp() throws Exception {
            super.setUp();
           }
           protected void tearDown() throws Exception {
             super.tearDown();
           }
           public  void testCompareDateTime(){  
            String dateTime1="20120111 01:02:03";
            String dateTime2="20130111 01:02:03";
            String dateTime3="20130111 01:02:03";  
            assertEquals(-1, DateUtil.compareDateTime(dateTime1, dateTime2));
            assertEquals(1,  DateUtil.compareDateTime(dateTime2, dateTime1));
            assertEquals(0,  DateUtil.compareDateTime(dateTime2, dateTime3));
           }
          }

            經(jīng)過運(yùn)行單元測試代碼,可以驗(yàn)證com.loggingselenium.DateUtil類的compareDateTime(String dateTime1, String dateTime2)的功能已經(jīng)實(shí)現(xiàn)了,可以用來比較兩個(gè)日期時(shí)間的大小了。

            對方法進(jìn)行多線程測試ThreadTestDateUtil

            雖然通過了單元測試,這個(gè)方法的功能實(shí)現(xiàn)了,但在多線程并發(fā)調(diào)用該方法的時(shí)候會(huì)出現(xiàn)拋出異常。手寫多線程并發(fā)測試代碼,com.loggingselenium.ThreadTestDateUtil繼承java.lang.Thread線程類,重新實(shí)現(xiàn)其run()方法,用于調(diào)用com.loggingselenium.DateUtil類的compareDateTime(String dateTime1, String dateTime2)。在main()方法中創(chuàng)建兩個(gè)線程并啟動(dòng)線程執(zhí)行調(diào)用日期時(shí)間比較的方法。

          package com.loggingselenium;
          public class ThreadTestDateUtil extends Thread {
           public void run() {
            int i1=DateUtil.compareDateTime("20130111 01:02:03","20130111 01:02:03");
            int i2=DateUtil.compareDateTime("20120111 01:02:03","20130111 01:02:03");
            System.out.println("i1="+i1);
            System.out.println("i2="+i2);
           }
           public static void main(String a[]) {  
            Thread t = new ThreadTestDateUtil();
            t.start();
            Thread t2 = new ThreadTestDateUtil();
            t2.start();
           }
          }

            編譯、運(yùn)行該方法,控制臺(tái)報(bào)異常:

            java.lang.RuntimeException: 解析日期時(shí)間格式出錯(cuò),期望的字符串格式為[yyyyMMdd HH:mm:ss]

            at DateUtil.compareDateTime(DateUtil.java:43)

            at TestDateUtil2.run(TestDateUtil2.java:3)

            使用JUnitPerf進(jìn)行多線程測試JUnitPerfTestDateUtil

            我們手寫多線程并發(fā)測試代碼的一個(gè)弊端是,如果我們需要測試100個(gè)線程,我們就需要?jiǎng)?chuàng)建100個(gè)線程實(shí)例Thread t,t1,t2,t3……并一一啟動(dòng)這些線程。JunitPerf包可以幫助我們更容易對代碼進(jìn)行多線程并發(fā)測試。

            首先,訪問http://www.clarkware.com/software/junitperf-1.9.1.zip下載我們需要的junitperf-1.9.1.jar,放到我們單元測試項(xiàng)目的構(gòu)建路徑。

            在測試代碼com.loggingselenium. UnitTestDateUtil的基礎(chǔ)上進(jìn)行修改,創(chuàng)建新測試類JUnitPerfTestDateUtil,以使用JunitPerf進(jìn)行多線程并發(fā)測試。新測試類中compareDateTimeLoadTestMethod()實(shí)現(xiàn)以5個(gè)線程執(zhí)行testCompareDateTime(),這個(gè)單元測試方法調(diào)用我們的日期時(shí)間比較方法。方法compareDateTimeLoadTestMethod()只會(huì)運(yùn)行1次,會(huì)有5個(gè)線程運(yùn)行方法testCompareDateTime(),等于有5個(gè)線程調(diào)用方法compareDateTime(String dateTime1, String dateTime2)。我們可以指定需要的線程數(shù)目,JunitPerf也提供了豐富的接口供我們選用。

          package com.loggingselenium;
          import com.clarkware.junitperf.LoadTest;
          import com.clarkware.junitperf.TestMethodFactory;
          import junit.framework.Test;
          import junit.framework.TestCase;
          import junit.framework.TestSuite;
          public class JUnitPerfTestDateUtil extends TestCase {
           public JUnitPerfTestDateUtil(String name) {
            super(name);
           }
           protected void setUp() throws Exception {
            super.setUp();
           }
           protected void tearDown() throws Exception {
            super.tearDown();
           }
           public void CompareDateTime() {
            String dateTime1 = "20120111 01:02:03";
            String dateTime2 = "20130111 01:02:03";
            String dateTime3 = "20130111 01:02:03";
            assertEquals(-1, DateUtil.compareDateTime(dateTime1, dateTime2));
            assertEquals(1, DateUtil.compareDateTime(dateTime2, dateTime1));
            assertEquals(0, DateUtil.compareDateTime(dateTime2, dateTime3));
           }
           protected static Test compareDateTimeLoadTestMethod() {
            int users = 5;
            Test factory = new TestMethodFactory(JUnitPerfTestDateUtil.class,
              "CompareDateTime");
            Test loadTest = new LoadTest(factory, users);
            return loadTest;
           }
           public static Test suite() {
            TestSuite suite = new TestSuite();
            suite.addTest(compareDateTimeLoadTestMethod());
            return suite;
           }
           public static void main(String args[]) {
            junit.textui.TestRunner.run(suite());
           }
          }


            編譯、運(yùn)行該測試方法,使用Run as Application,控制臺(tái)可能輸出如下結(jié)果,有2個(gè)Error:

            …..EE

            Time: 0.053

            There were 2 errors:

            1) CompareDateTime(com.loggingselenium.JUnitPerfTestDateUtil)java.lang.RuntimeException: 解析日期時(shí)間格式出錯(cuò),期望的字符串格式為[yyyyMMdd HH:mm:ss]

            at com.loggingselenium.DateUtil.compareDateTime(DateUtil.java:18)
            at com.loggingselenium.JUnitPerfTestDateUtil.CompareDateTime(JUnitPerfTestDateUtil.java:22)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at com.clarkware.junitperf.TestFactory.run(TestFactory.java:83)
            at com.clarkware.junitperf.ThreadedTest$TestRunner.run(ThreadedTest.java:75)
            at java.lang.Thread.run(Unknown Source)

            2) CompareDateTime(com.loggingselenium.JUnitPerfTestDateUtil)java.lang.RuntimeException: 解析日期時(shí)間格式出錯(cuò),期望的字符串格式為[yyyyMMdd HH:mm:ss]

            at com.loggingselenium.DateUtil.compareDateTime(DateUtil.java:18)
            at com.loggingselenium.JUnitPerfTestDateUtil.CompareDateTime(JUnitPerfTestDateUtil.java:22)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at com.clarkware.junitperf.TestFactory.run(TestFactory.java:83)
            at com.clarkware.junitperf.ThreadedTest$TestRunner.run(ThreadedTest.java:75)
            at java.lang.Thread.run(Unknown Source)

            FAILURES!!!

            Tests run: 5, Failures: 0, Errors: 2

            多線程并發(fā)測試失敗,我們的比較日期時(shí)間大小的方法存在線程不安全的問題,我們需要在DateUtil中方法前加上線程同步關(guān)鍵字synchronized:

          public synchronized static int compareDateTime(String dateTime1, String dateTime2) {......}

            再次運(yùn)行單元測試方法,可以發(fā)現(xiàn)多線程并發(fā)下存在的問題得到了解決。

          版權(quán)聲明:本文出自 lobster 的51Testing軟件測試博客:http://www.51testing.com/?194329

          原創(chuàng)作品,轉(zhuǎn)載時(shí)請務(wù)必以超鏈接形式標(biāo)明本文原始出處、作者信息和本聲明,否則將追究法律責(zé)任。

          posted on 2013-01-14 11:55 順其自然EVO 閱讀(433) 評(píng)論(0)  編輯  收藏 所屬分類: 測試學(xué)習(xí)專欄

          <2013年1月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 阿鲁科尔沁旗| 买车| 白沙| 乐平市| 大厂| 旺苍县| 淄博市| 五指山市| 吉林省| 纳雍县| 通州市| 桓台县| 昭平县| 兴安县| 措美县| 阿图什市| 北川| 依安县| 社会| 贡嘎县| 惠东县| 五原县| 从化市| 无为县| 屯门区| 宝丰县| 绥滨县| 江孜县| 进贤县| 西和县| 临沭县| 嘉义县| 襄樊市| 湾仔区| 横峰县| 广州市| 通江县| 龙海市| 醴陵市| 喜德县| 洛南县|