JUnit4の落とし穴(アノテーションは継承されない)
うーん,落とし穴っていうほど大げさなモノじゃないんだけど,JUnit3当たり前にできてたことがJUnit4でできないものもあるよって話。その代表例が,アノテーションの継承ができない事。
事の善し悪しは置いておくが,よくテストケースのバリエーション作りに,親(抽象)クラスに基本となるテストメソッドを定義しておき,それをテンプレとして子(具象)クラスでパラメタ変えたりしてたわけだ。簡単にコードで示すとこんな事。
public class JUnit3Super extends TestCase { public void testテストケース1() { ... } public void testテストケース2() { ... } } public class JUnit3SampleTest extends JUnit3Super { }
当たり前だが,JUnit3SampleTestにはJUnit3Superのテストケースが継承されるので,問題なくテストを実行できる。だけど,これがJUnit4になるとそうはいかない。JUni4流に書き直すと,
public class JUnit4Super { @Test public void テストケース1() { ... } @Test public void テストケース2() { ... } } public class JUnit4SampleTest extends JUnit4Super { }
って感じなるんだが,残念なことにアノテーションは継承されないので,JUnit4SampleTestはテストハーネスとして認識されんのだ。こんな事はJDK5の言語仕様を知ってりゃ,至極当然のことなので,なにも騒ぎ立てる話じゃないんだけど,まあちょっと残念ではある。
ここでちょっと視点を変えるが,JUnit3/JUnit4と区別して話をしているが,JUnit4のJarファイル(junit-4.4.jarとかjunit-4.3.jar)にはJUnit3も含まれているのだ(JUnit4のorg.junit
パッケージだけじゃなく,JUnit3のjunit.framework
パッケージも含まれている)。
だから,テストケースはJUnit3流でアサーションはJUnit4流,なんてハイブリッドだってOKなのだ。
import junit.framework.TestCase; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; public class JUnit34Test extends TestCase { public void testテスト() { assertThat(true, is(true)); } }
スクリーンショットを貼れないのが残念だが,IDEAで試してみたらJUnit3流/JUnit4流/そのハイブリッドが同じテストディレクトリに混在していても,すべてテストケースと認識したしテストの実行もできた。だから,JUnit4を使ったからと言ってムリに@Testアノテーションを使う必要はないのかも知れない。
#他のIDE?そんなの知らんよ。:-P
なんにせよ,JUnit4に慣れるまで,もちょっと試行錯誤が必要だ。
(追記)コメントより,JUnitのテストランナーはクラス階層をさかのぼってアノテーションを判別してくれる。なんで,イケてないのは,@Testアノテーションがないとテストハーネスだと認識できないIDE側だったという話。
テストランナーに載せてしまえばこっちのものなので,IDEをだまくらかすために,こんなふうにダミーを置いておく手もあるが,それってどうなんだろ?
public class JUnit4Super { @Test public void テストケース1() { ... } @Test public void テストケース2() { ... } } public class JUnit4SampleTest extends JUnit4Super { @Test public void ダミー() {} }