性能測定ツール類——TimeMeasureUtil&TimeMeasureProxy


TimeMeasureUtil:単一時間測定を行います.
1.startTimeとendTimeの両方が正しく設定されていることを確認するために、インスタンスオブジェクトを使用して実装します.測定のたびに、対象が正しい状態にあるかどうかを判断することができます.
2、このクラスはツールクラスであり、テスト時に多くのオブジェクトインスタンスが発生してもソフトウェアには何の影響もありません.
public class TimeMeasureUtil {
	private long startTime = 0;
	private long endTime = 0;
	
	private TimeMeasureUtil(){
		
	}
	
	public static TimeMeasureUtil newInstance(){
		return new TimeMeasureUtil();
	}
	
	public void start(){
		startTime = System.currentTimeMillis();
	}
	
	public void end(){
		endTime = System.currentTimeMillis();
	}
	
	public long measure(){
		
		// Invalid: Before y
		if( startTime == 0 ){
			throw new IllegalStateException( "Must call metod start() first, when call method measure()." );
		}
		if( endTime == 0 ){
			throw new IllegalStateException( "Must call metod end() first, when call method measure()." );
		}
		if( startTime > endTime ){
			throw new IllegalStateException( "Must call metod start() first, when call method end()." );
		}
		
		return endTime - startTime;
	}

}

使用例:
	@Test
	public void testMeasure_ok() {
		TimeMeasureUtil timeUtil = TimeMeasureUtil.newInstance();
		timeUtil.start();
		
		//  
		try {
			Thread.sleep( 1000 );
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		timeUtil.end();
		
		assertEquals( 1000, timeUtil.measure() );
	}

単回測定の可能性のばらつきが大きいため、統計的意義がなく、以下のような測定平均時間!
TimeMeasureProxy:
1、デフォルト運行20回平均
2、与えられた運行回数の平均
欠陥:
1、反射で実現されるため、パラメータはObject[]で伝達される.元のタイプがあります(byte,int,char...)パラメータの方法はテストできません!テストはTimeMeasureUtilのみで実行できます. 
2、初めてメソッドを実行した後に、あるプロパティが変更された場合、そのプロパティが変更された後に、次のメソッドの実行に影響を与える可能性があります(異なる時間がある可能性があります).このようなメソッドはテストできません.可能な改善点:count個のオブジェクトをクローンし、同じ属性のオブジェクトでメソッドを実行します(オブジェクトごとにメソッドを1回実行します).このような要件のため、被テストクラスは「クローン」メソッドを提供し、「テストによって論理に影響を与える」ことは望ましくないため、実装されていない.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TimeMeasureProxy {
	
	// default measure count
	private int count = 20;
	
	private TimeMeasureProxy(){
		
	}
	
	private TimeMeasureProxy( int count ){
		this.count = count;
	}
	
	public static TimeMeasureProxy newInstance(){
		return new TimeMeasureProxy();
	}
	
	public static TimeMeasureProxy newInstance( int count ){
		return new TimeMeasureProxy( count );
	}
	
	public long avgTime( Object owner, String methodName, Object[] args ){
		
		// valid parameters.
		if( owner == null ){
			throw new IllegalStateException("owner can't be null.");
		}
		if( methodName == null ){
			throw new IllegalStateException("methodName can't be null.");
		}
		
		Class<?> ownerClass = owner.getClass();
		Class<?>[] argsClass = null;
		if( args != null ){
			argsClass = new Class[ args.length ];
			for( int i=0 ; i<args.length ; i++ ){
				argsClass[i] = args[i].getClass();
			}
		}

		Method method;
		try {
			method = ownerClass.getMethod( methodName, argsClass );
		} catch (SecurityException e) {
			throw new RuntimeException( e );
			
		} catch (NoSuchMethodException e) {
			throw new RuntimeException( e );
		}
		
		return totalTime( owner, method, args)/count;
	}
	
	long totalTime( Object owner, Method method, Object[] args ){
		long totalTime = 0;
		
		try {
			for( int i=0; i<count ; i++ ){
				TimeMeasureUtil timeUtil = TimeMeasureUtil.newInstance();
				timeUtil.start();
				method.invoke( owner, args );
				timeUtil.end();
				totalTime += timeUtil.measure();
			}
		} catch (IllegalArgumentException e) {
			throw new RuntimeException( e );
		} catch (IllegalAccessException e) {
			throw new RuntimeException( e );
		} catch (InvocationTargetException e) {
			throw new RuntimeException( e );
		}
		
		return totalTime;
	}

}

使用例:
1、テスト対象のクラス
class ForMeasureAvgTime{
	
	public void justForTest(){
		try {
			Thread.sleep( 335 );
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void justForTestWithParams( Integer age, String name ){
		try {
			Thread.sleep( 558 );
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

2、TimeMeasureProxyでテストする
	@Test
	// & (20)
	public void testAvgTime_defaultCount() {
		ForMeasureAvgTime forMeasure = new ForMeasureAvgTime();
		
		TimeMeasureProxy proxy = TimeMeasureProxy.newInstance();
		long avgTime = proxy.avgTime( forMeasure, "justForTest", null );
		
		System.out.println( "avgTime=" + avgTime );
		assertTrue( (avgTime - 335) < 5 || (335 - avgTime) < 5);
	}
	
	@Test
	// & (10)
	public void testAvgTime_giveCount() {
		ForMeasureAvgTime forMeasure = new ForMeasureAvgTime();
		
		TimeMeasureProxy proxy = TimeMeasureProxy.newInstance( 10 );
		long avgTime = proxy.avgTime( forMeasure, "justForTestWithParams", new Object[]{24, "GongQiang"} );
		
		System.out.println( "avgTime=" + avgTime );
		assertTrue( (avgTime - 558) < 5 || (558 - avgTime) < 5);
	}