JUnit テストRunnerの拡張

テストを行う際にしておきたいこと(テスト対象プログラムの起動やテスト対象への接続)をRunnerに記述した。その概要メモ。
テストでこのRunnerを使えばテストコードにはテストのコードだけ書けばすむ。Before/Afterアノテーションでやれば良いじゃんという気もするけれど、毎テスト毎に書かなくて良いのが便利?
追記:JUnitのバージョンは4.5

package hogehoge

import java.io.IOException;

import org.apache.log4j.Logger;
import org.junit.Assert;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;

public class CombinedTestRunner extends BlockJUnit4ClassRunner {

	private Server server;
	private TestOperation operation;
	
	private Logger logger = Logger.getLogger(CombinedTestRunner.class);
	
	public CombinedTestRunner(Class<?> klass) throws InitializationError {
		super(klass);
		logger.debug("[init] start.");
		// 初期化処理
		logger.debug("[init] end.");
	}

	protected TestOperation createIntegrationTestOp() {
		return new TestOperation();
	}
	
	@Override
	public void run(RunNotifier notifier) {
		try {
			server.start();
			operation.connect();

			// テストクラス実行
			super.run(notifier);

			operation.disconnect();
			server.stop();
		} catch (IOException ioe) {
			logger.fatal("[run] exception on connect/disconnect.", ioe);
		}
	}
	
	@Override
	public void runChild(FrameworkMethod method, RunNotifier notifier) {
		// テストメソッドの実行前に実行
		try {
			operation.reset();
		} catch (Exception ioe) {
			logger.fatal("[methodBlock] exception on reset.", ioe);
			throw new RuntimeException(ioe); // ParentRunner.run() でキャッチされる		
		}
		
		super.runChild(method, notifier);
		
		// テストメソッドの実行後に実行
		try {
			if (operation.checkIfDataIsPooled()) {
				String testName = method.getName();
				StringBuilder builder = new StringBuilder(1024);
				builder.append(testName).append(" : received data is still left in the queue.\n");
				while (operation.checkIfDataIsPooled()) {
					String received = operation.receive(); // 捨てる兼ログ
					builder.append(received);
				}
				Assert.fail(builder.toString());
			}
		} catch (Exception e) {
			logger.fatal("[methodBlock] exception on queue check.", e);
			throw new RuntimeException(e); // ParentRunner.run() でキャッチされる	
		}
	}
}

テストクラスにRunWithアノテーションをつけて、Runnerを指定

package hogehoge

import org.junit.runner.RunWith;

@RunWith(CombinedTestRunner.class)
public class TestHogeHoge {
 ...