2011年9月24日土曜日

JUnitのRuleパッケージについて調査

最近JUnit 4.9がリリースされました。
ClassRule,TestRuleの変更がありました。
TestWatchmanがdeprecatedになってTestWatcherに置き換わるなど。

Ruleのパッケージについて、あまり知らなかったので、調べて、まとめてみました。


TestName
現在のテストメソッドの情報等を取得する。

public class SampleClassTest {
 @Rule
 public TestName name = new TestName();
 @Test
 public void test() {
  System.out.println(name.getMethodName());
  fail("Not yet implemented");
        }
}

ErrorCollector
読んで字の通り、例外を集めて保持するクラスです。例外をaddして、最後のverifyでaddされたエラーの個数などでチェックをかけます。

public class TestExternalResource {
 @Rule
 public ErrorCollector collector = new ErrorCollector() {
  protected void verify() throws Throwable {

   System.out.println("[ErrorCollector]");
   super.verify();
  };
 };

 @Test
 public void test() {
  collector.addError(new Throwable("first thing went wrong"));
  collector.addError(new Throwable("second thing went wrong"));
  int sample = 1;
  collector.checkThat(0, is(sample));

 }
}

ExpectedException
例外を制御する構文です。@Test(expected=NullPointerException.class)と同じような意味ですが、もうちょっと
拡張性を高くしたい場合に使えます。

public class TestExpectedException {
 @Rule
 public ExpectedException thrown = ExpectedException.none();

 @Test
 public void throwsNothing() {
  // no exception expected, none thrown: passes.
 }

 @Test
 public void throwsNullPointerException() {
  thrown.expect(NullPointerException.class);
  throw new NullPointerException();
 }

 @Test
 public void throwsNullPointerExceptionWithMessage() {
  Matcher[] allowedExceptionMatchers = {
    is(NullPointerException.class),
    is(IllegalArgumentException.class) };
  thrown.expect(anyOf(allowedExceptionMatchers));
  thrown.expectMessage("happened?");
  throw new NullPointerException("What happened?");
 }

}

TemporaryFolder
/tmp以下にファイルやディレクトリをおく場合に使えるクラスです。

public class TestTemporaryFolder {
 @Rule
 public TemporaryFolder folder = new TemporaryFolder();

 @Test
 public void test() throws IOException {
  File createFile = folder.newFile("myFile.txt");
  File createFolder = folder.newFolder("subFolder");
  System.out.println("Path:" + createFile.getAbsolutePath());
  System.out.println("Path:" + createFolder.getAbsolutePath());
 }

}


Timeout
メソッドのタイムアウト監視クラスです。メソッドの実行時間のチェック等に使います。

public class TestTimeout {
 @Rule
 public MethodRule globalTimeout = new Timeout(1000);

 @Test
 public void test() {
  for (;;)
   ;
 }

}


Verifier
テストが成功した後に、チェックする仕組みを入れたい場合このクラスを利用します。

public class TestVerifier {
 private ErrorLog error = new ErrorLog();

 @Rule
 public MethodRule verifier = new Verifier() {
  @Override
  public void verify() {
   System.out.println("[Verifier]");
   assertTrue(error.isEmpty());
  }
 };
 @Test
 public void test() {
  fail("Not yet implemented");
 }

 @Test
 public void test2() {
  error.add("sample");
 }
}



TestWatchman(TestWatcher)
テストケースの結果をテスト実施後すぐに確認したい場合に使えます。
public class TestTestWachman {
 private static String watchedLog;

 @Rule
 public MethodRule watchman = new TestWatchman() {
  @Override
  public void failed(Throwable e, FrameworkMethod method) {
   System.out.println("[watch]fail");
   watchedLog += method.getName() + " " + e.getClass().getSimpleName()
     + "\n";
  }

  @Override
  public void succeeded(FrameworkMethod method) {
   System.out.println("[watch]success");
   watchedLog += method.getName() + " " + "success!\n";
  }
 };

 @Test
 public void test() {
  fail("Not yet implemented");
 }

 @Test
 public void test2() {

 }

}


ExternalResource
外部リソースなどのアクセスをテスト前後で行いたい場合に利用します。だいたいDBにアクセスしたり、ファイルアクセスだったりすると思います。クラスをインスタンス化したら、そのクラスのテスト前後にExternalResourceのbefore,afterが実行されます。


public class SampleClassTest {
 @Rule
 public ExternalResource resource = new ExternalResource() {
  Server myServer = new Server();
  @Override
  protected void after() {
   // 外部リソースの接続解除
   System.out.println("[ExternalResrouce after]");
   myServer.disconnect();
  }

  @Override
  protected void before() throws Throwable {
   // 外部リソース接続
   System.out.println("[ExternalResrouce before]");
   myServer.connect();
  }
 };
 @Test
 public void test() {
        }
}


テストメソッドの実行前後に起動されるメソッドの順序を調べてみました。

ExternalResource Before
Before
After
【テストメソッド実行】
ErrorCollector
Verifier
TestWatchman
ExternalResource After



同じ機能っぽいじゃないか?と思うクラスがあるとは思いますが、ユースケース別に
使い分けると非常によいクラスになると思うので、うまく使い分けていきましょう。
次はhamcrestあたりかな。

1 件のコメント: