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


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

簡介:
單元測試和性能測試在測試領域屬於要求相對較高的測試活動,也是測試工程師成長、向上發展的反向。單元測試評測我們的代碼實現功能的情況,性能測試則企圖分析應用程序的性能表現和負載能力。那么“單元性能測試”能做什么?我們可以這樣說,單元性能測試以單元測試的形式對代碼進行性能測試。單元性能測試像單元測試一樣,需要測試人員編寫測試代碼,但現在關注的不是代碼的功能實現情況了,而是想得到被測試代碼的性能數據,包括執行方法耗時、多線程並發是否線程安全、內存是否泄漏、是否存在短期循環對象等。單元性能測試相對於系統性能測試更容易定位問題,對關鍵的方法進行測試,可以降低系統性能風險,減少系統集成后系統性能測試的工作量。本篇文檔演示如何使用JUnitPerf程序包對代碼進行多線程並發測試。
待測代碼DateUtil:
我們待測的程序代碼為com.loggingselenium.DateUtil類。這個類中有一個私有靜態成員timeFormator和一個靜態方法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("解析日期時間格式出錯,期望的字符串格式為[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));
	}
}

經過運行單元測試代碼,可以驗證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()方法中創建兩個線程並啟動線程執行調用日期時間比較的方法。

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

編譯、運行該方法,控制台報異常:
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也提供了豐富的接口供我們選用。

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

編譯、運行該測試方法,使用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]
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

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

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

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

如果您喜歡本篇文章,強烈建議您去http://loggingselenium.com/逛逛!里面有您更多的值得一看的文章!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM