JUnit 4.10で使用できるアノテーション(org.junitパッケージ)

JUnit 4.10をEclipseで使えるようにしました。
EclipseでのJUnit 4.10の使い方

確か、JUnit 3系の時は「test」で始まるメソッドがテストメソッドとして
認識される仕様だったと思いますが、4系からはアノテーションの仕組みを取り入れ、
「@Test」を指定したメソッドがテストメソッドになります。

その他にもアノテーションはありますので、まずはorg.junitパッケージに
含まれているものを調べてみました。


org.junitパッケージに含まれるアノテーション
・テストメソッド指定:@Test
・テスト除外指定:@Ignore
・テストメソッドごとに事前実行:@Before
・テストを通して、一回だけ事前実行:@BeforeClass
・テストメソッドごとに事後実行:@After
・テストを通して、一回だけ事後実行:@AfterClass
・テスト時の一時的なルールの作成:@Rule
・複数のテストを通じてのルール設定:@ClassRule




テストメソッド指定:@Test



「@Test」を指定したメソッドがテストメソッドとして実行されます。
以前は、名前が「test」で始まるものが一律実行されていたと思います。

そのため、メソッド名はどのように命名してもかまいません。


  1. package sample;
  2. import static org.hamcrest.core.Is.is;
  3. import static org.junit.Assert.assertThat;
  4. import org.junit.Test;
  5. public class MainTest {
  6.     
  7.     @Test
  8.     public void test1() {
  9.         assertThat("test1", is("test1"));
  10.     }
  11.     
  12.     @Test
  13.     public void hoge() {
  14.         assertThat("hoge", is("hoge"));
  15.     }
  16. }




test1,hoge共に実行されます。

99_001.png




メソッド名がtestで始まっていても、@Testをつけていない場合、

  1. package sample;
  2. import static org.hamcrest.core.Is.is;
  3. import static org.junit.Assert.assertThat;
  4. import org.junit.Test;
  5. public class MainTest {
  6.     
  7.     public void test1() {
  8.         assertThat("test1", is("test1"));
  9.     }
  10.     
  11.     @Test
  12.     public void hoge() {
  13.         assertThat("hoge", is("hoge"));
  14.     }
  15. }




テストケースとはみなされず、test1は実行されません。

99_002.png






テスト除外指定:@Ignore



一時的にテストケースから除外したい場合に使用します。


  1. package sample;
  2. import static org.hamcrest.core.Is.is;
  3. import static org.junit.Assert.assertThat;
  4. import org.junit.Ignore;
  5. import org.junit.Test;
  6. public class MainTest {
  7.     
  8.     @Ignore
  9.     @Test
  10.     public void test1() {
  11.         assertThat("test1", is("test1"));
  12.     }
  13.     
  14.     @Test
  15.     public void hoge() {
  16.         assertThat("hoge", is("hoge"));
  17.     }
  18. }




@Ignoreを指定した場合は、テストケースとして認識はされますが
実行はされません。

99_003.png






テストメソッドごとに事前実行:@Before



各テストメソッドを実行する前に、オブジェクトの初期化処理などを
実行したい場合に使用します。


  1. package sample;
  2. import org.junit.Before;
  3. import org.junit.Test;
  4. public class MainTest {
  5.     
  6.     @Before
  7.     public void before() {
  8.         System.out.println("@before");
  9.     }
  10.     
  11.     @Test
  12.     public void test1() {
  13.         System.out.println("@test - test1");
  14.     }
  15.     
  16.     @Test
  17.     public void hoge() {
  18.         System.out.println("@test - hoge");
  19.     }
  20. }




コンソールには、このように出力されます。

@before
@test - test1
@before
@test - hoge




99_004.png







テストを通して、一回だけ事前実行:@BeforeClass



@Beforeだと、テストメソッド毎に実行されますが、
@BeforeClassを使用すると、テストを実行する前に一度だけ
処理を行うことができます。

注意点として、@BeforeClassを指定するメソッドはstaticじゃないといけません。
staticにしなかった場合、java.lang.Exception: Method beforeClass() should be staticという
エラーが発生します。


  1. package sample;
  2. import org.junit.BeforeClass;
  3. import org.junit.Test;
  4. public class MainTest {
  5.     
  6.     @BeforeClass
  7.     public static void beforeClass() {
  8.         System.out.println("@beforeClass");
  9.     }
  10.     
  11.     @Test
  12.     public void test1() {
  13.         System.out.println("@test - test1");
  14.     }
  15.     
  16.     @Test
  17.     public void hoge() {
  18.         System.out.println("@test - hoge");
  19.     }
  20. }




コンソールには、このように出力されます。

@beforeClass
@test - test1
@test - hoge



99_005.png









テストメソッドごとに事後実行:@After



@Afterを指定したメソッドは、各々のテストメソッドを実行した後に呼び出されます。


  1. package sample;
  2. import org.junit.After;
  3. import org.junit.Test;
  4. public class MainTest {
  5.     
  6.     @After
  7.     public void after() {
  8.         System.out.println("@after");
  9.     }
  10.     
  11.     @Test
  12.     public void test1() {
  13.         System.out.println("@test - test1");
  14.     }
  15.     
  16.     @Test
  17.     public void hoge() {
  18.         System.out.println("@test - hoge");
  19.     }
  20. }




コンソールには、このように出力されます。

@test - test1
@after
@test - hoge
@after



99_006.png









テストを通して、一回だけ事後実行:@AfterClass



@BeforeClassの逆です。
@AfterClassを指定したメソッドは、テスト終了前に一回だけ実行されます。

@BeforeClassと同じく、statcメソッドじゃないといけません。


  1. package sample;
  2. import org.junit.AfterClass;
  3. import org.junit.Test;
  4. public class MainTest {
  5.     
  6.     @AfterClass
  7.     public static void afterClass() {
  8.         System.out.println("@afterClass");
  9.     }
  10.     
  11.     @Test
  12.     public void test1() {
  13.         System.out.println("@test - test1");
  14.     }
  15.     
  16.     @Test
  17.     public void hoge() {
  18.         System.out.println("@test - hoge");
  19.     }
  20. }




コンソールにはこのように出力されます。

@test - test1
@test - hoge
@afterClass




99_007.png






テスト時の一時的なルールの作成:@Rule



説明が正しいか自身がないですが、
・TemporaryFolder
・ExternalResource
・ErrorCollector
・ExpectedException
・Timeout
このような機能があります。

【参考】
JUnit 4.7 : テストごとのルール
http://www.infoq.com/jp/news/2009/07/junit-4.7-rules


サンプルとして、例えば0除算を行った時
「java.lang.ArithmeticException: / by zero」
というエラーが発生しますが、メッセージを独自の日本語表記で
エラーをthrowするメソッドのテストを考えてみます。


※サンプルなので、いきなりエラーを発生させています。

  1.     private void calc() throws RuntimeException {
  2.         throw new ArithmeticException("ゼロ除算が発生しました。");
  3.     }





これをテストするサンプルはこんな感じになるかと。

  1. package sample;
  2. import org.junit.Rule;
  3. import org.junit.Test;
  4. import org.junit.rules.ExpectedException;
  5. public class MainTest {
  6.     
  7.     @Rule
  8.     public ExpectedException exception = ExpectedException.none();
  9.     
  10.     @Test
  11.     public void test() {
  12.         exception.expect(ArithmeticException.class);
  13.         exception.expectMessage("ゼロ除算が発生しました");
  14.         calc();
  15.     }
  16.     
  17.     private void calc() throws RuntimeException {
  18.         throw new ArithmeticException("ゼロ除算が発生しました。");
  19.     }
  20. }



上記のテストケースはOKで通過します。


今度は、普通に0除算して通常のエラーメッセージでのエラーを発生させてみます。

  1. package sample;
  2. import org.junit.Rule;
  3. import org.junit.Test;
  4. import org.junit.rules.ExpectedException;
  5. public class MainTest {
  6.     
  7.     @Rule
  8.     public ExpectedException exception = ExpectedException.none();
  9.     
  10.     @Test
  11.     public void test() {
  12.         exception.expect(ArithmeticException.class);
  13.         exception.expectMessage("ゼロ除算が発生しました");
  14.         calc();
  15.     }
  16.     
  17.     private void calc() throws RuntimeException {
  18.         int a = 1/0;
  19.     }
  20. }




実行すると、結果はNGとなりました。

java.lang.AssertionError:
Expected: (exception with message a string containing "ゼロ除算が発生しました" and an instance of java.lang.ArithmeticException)
     got: <java.lang.ArithmeticException: / by zero>



99_008.png








複数のテストを通じてのルール設定:@ClassRule



@ClassRuleは、@SuiteClassesを使用して複数のテストクラスを実行するときに
威力を発揮するようです。

まず、テストクラスA

  1. package sample;
  2. import org.junit.Test;
  3. public class A {
  4.     @Test
  5.     public void test1() {
  6.         System.out.println("@test - A - test1");
  7.     }
  8.     
  9.     @Test
  10.     public void hoge() {
  11.         System.out.println("@test - A - hoge");
  12.     }
  13. }




そして、テストクラスB

  1. package sample;
  2. import org.junit.Test;
  3. public class B {
  4.     @Test
  5.     public void test1() {
  6.         System.out.println("@test - B - test1");
  7.     }
  8.     
  9.     @Test
  10.     public void hoge() {
  11.         System.out.println("@test - B - hoge");
  12.     }
  13. }




AとBをまとめて実行するMainTest

  1. package sample;
  2. import org.junit.ClassRule;
  3. import org.junit.rules.ExternalResource;
  4. import org.junit.runner.RunWith;
  5. import org.junit.runners.Suite;
  6. import org.junit.runners.Suite.SuiteClasses;
  7. @RunWith(Suite.class)
  8. @SuiteClasses({A.class, B.class})
  9. public class MainTest {
  10.     
  11.     @ClassRule
  12.     public static ExternalResource resource= new ExternalResource() {
  13.         @Override
  14.         protected void before() throws Throwable {
  15.             System.out.println("@before - MainTest");
  16.         };
  17.         
  18.         @Override
  19.         protected void after() {
  20.             System.out.println("@after - MainTest");
  21.         };
  22.     };
  23. }




こんなサンプルを作成して実行してみると、コンソールはこんな出力になりました。

@before - MainTest
@test - A - test1
@test - A - hoge
@test - B - test1
@test - B - hoge
@after - MainTest



99_009.png


使用用途は、データベースのコネクションや、サーバーのソケットを
staticオブジェクトとしてMainTestに宣言。

beforeで接続、afterで切断するようにしておきます。

各々のテストケースでは、MainTestで宣言しているオブジェクトを
参照してテストを実行するようにしておけば、コネクション作成の負荷が
1回に抑えられるという使い方のようです。





【参考URL】

Package org.junit
http://kentbeck.github.com/junit/javadoc/latest/

JUnit 4.7 : テストごとのルール
http://www.infoq.com/jp/news/2009/07/junit-4.7-rules

関連記事

コメント

初めまして。

勉強させていただきます!
非公開コメント

プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
Symfoware まとめ

PR




検索フォーム

月別アーカイブ