天天看點

單元性能測試之使用JUnitPerf測試多線程并發

簡介:

  待測代碼dateutil:

  我們待測的程式代碼為com.loggingselenium.dateutil類。這個類中有一個私有靜态成員timeformator和一個靜态方法comparedatetime(string datetime1, string datetime2)。

package com.loggingselenium;

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("解析日期時間格式出錯,期望的字元串格式為[yyyymmdd hh:mm:ss]");

  }

 }

}

  單元測試代碼unittestdateutil:

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

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));

  經過運作單元測試代碼,可以驗證com.loggingselenium.dateutil類的comparedatetime(string datetime1, string datetime2)的功能已經實作了,可以用來比較兩個日期時間的大小了。

  對方法進行多線程測試threadtestdateutil

  雖然通過了單元測試,這個方法的功能實作了,但在多線程并發調用該方法的時候會出現抛出異常。手寫多線程并發測試代碼,com.loggingselenium.threadtestdateutil繼承java.lang.thread線程類,重新實作其run()方法,用于調用com.loggingselenium.dateutil類的comparedatetime(string datetime1, string datetime2)。在main()方法中建立兩個線程并啟動線程執行調用日期時間比較的方法。

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();

  編譯、運作該方法,控制台報異常:

  java.lang.runtimeexception: 解析日期時間格式出錯,期望的字元串格式為[yyyymmdd hh:mm:ss]

  at dateutil.comparedatetime(dateutil.java:43)

  at testdateutil2.run(testdateutil2.java:3)

  使用junitperf進行多線程測試junitperftestdateutil

  我們手寫多線程并發測試代碼的一個弊端是,如果我們需要測試100個線程,我們就需要建立100個線程執行個體thread t,t1,t2,t3……并一一啟動這些線程。junitperf包可以幫助我們更容易對代碼進行多線程并發測試。

  首先,通路http://www.clarkware.com/software/junitperf-1.9.1.zip下載下傳我們需要的junitperf-1.9.1.jar,放到我們單元測試項目的建構路徑。

  在測試代碼com.loggingselenium. unittestdateutil的基礎上進行修改,建立新測試類junitperftestdateutil,以使用junitperf進行多線程并發測試。新測試類中comparedatetimeloadtestmethod()實作以5個線程執行testcomparedatetime(),這個單元測試方法調用我們的日期時間比較方法。方法comparedatetimeloadtestmethod()隻會運作1次,會有5個線程運作方法testcomparedatetime(),等于有5個線程調用方法comparedatetime(string datetime1, string datetime2)。我們可以指定需要的線程數目,junitperf也提供了豐富的接口供我們選用。

import com.clarkware.junitperf.loadtest;

import com.clarkware.junitperf.testmethodfactory;

import junit.framework.test;

import junit.framework.testsuite;

public class junitperftestdateutil extends testcase {

 public junitperftestdateutil(string name) {

  super(name);

  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(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());

  編譯、運作該測試方法,使用run as application,控制台可能輸出如下結果,有2個error:

  …..ee

  time: 0.053

  there were 2 errors:

  1) comparedatetime(com.loggingselenium.junitperftestdateutil)java.lang.runtimeexception: 解析日期時間格式出錯,期望的字元串格式為[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: 解析日期時間格式出錯,期望的字元串格式為[yyyymmdd hh:mm:ss]

  failures!!!

  tests run: 5, failures: 0, errors: 2

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

public synchronized static int comparedatetime(string datetime1, string datetime2) {......}

  再次運作單元測試方法,可以發現多線程并發下存在的問題得到了解決。

====================================分割線================================

最新内容請見作者的github頁:http://qaseven.github.io/

繼續閱讀