#navi_header|Java| JUnit 4.8.1 使用中に、 public class FooTest extends TestCase { @Test public void foo { assertTrue(true); } } がElipse/Maven双方から認識されない現象に遭遇したのでメモ。 環境: JUnit : 4.8.1 POM : junit junit 4.8.1 test Maven : 2.2.1 Eclipse : 3.5 Galileo org.eclipse.jdt.junit (3.5.1.r351_v20090708-0800) org.eclipse.jdt.junit.runtime (3.4.100.v20090513-2000) org.eclipse.jdt.junit4.runtime (1.1.0.v20090513-2000) org.eclipse.pde.junit.runtime (3.4.0.v20090527) org.junit (3.8.2.v20090203-1005) org.junit4 (4.5.0.v20090824) JDK 1.6.12 Windows XP SP2 / 2GB RAM / Pen4 HT #more|| ---- * 現象 前掲のFooTestクラス一つだけの状態で、Eclipse上からJUnit実行 or "mvn test" を実行すると「テストケースが見つかりません」という趣旨のエラーになる。 発生時のスタックトレース(Eclipse経由): #pre||> junit.framework.AssertionFailedError: No tests found in echoes.act9.protocol.FooTest at junit.framework.Assert.fail(Assert.java:47) at junit.framework.TestSuite$1.runTest(TestSuite.java:97) at junit.framework.TestCase.runBare(TestCase.java:134) at junit.framework.TestResult$1.protect(TestResult.java:110) at junit.framework.TestResult.runProtected(TestResult.java:128) at junit.framework.TestResult.run(TestResult.java:113) at junit.framework.TestCase.run(TestCase.java:124) at junit.framework.TestSuite.runTest(TestSuite.java:232) at junit.framework.TestSuite.run(TestSuite.java:227) at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) ||< 発生時のスタックトレース(Maven経由): #pre||> ------------------------------------------------------------------------------- Test set: echoes.act9.protocol.FooTest ------------------------------------------------------------------------------- Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.094 sec <<< FAILURE! warning(junit.framework.TestSuite$1) Time elapsed: 0.016 sec <<< FAILURE! junit.framework.AssertionFailedError: No tests found in echoes.act9.protocol.FooTest at junit.framework.Assert.fail(Assert.java:47) at junit.framework.TestSuite$1.runTest(TestSuite.java:97) at junit.framework.TestCase.runBare(TestCase.java:134) at junit.framework.TestResult$1.protect(TestResult.java:110) at junit.framework.TestResult.runProtected(TestResult.java:128) at junit.framework.TestResult.run(TestResult.java:113) at junit.framework.TestCase.run(TestCase.java:124) at junit.framework.TestSuite.runTest(TestSuite.java:232) at junit.framework.TestSuite.run(TestSuite.java:227) at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83) at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62) at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140) at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127) at org.apache.maven.surefire.Surefire.run(Surefire.java:177) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345) at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009) ||< メソッド名に"test"接頭辞を付与すると認識され、テストケースが実行される。 * 原因 ClassRunnerの内部判定処理でJUnit3.8.x用のClassRunnerが選択されてしまう為、"@Test"アノテーションが認識されなかったことが原因。 Eclipse上のスタックトレース: ... at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) ... Maven上のスタックトレース: ... at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83) at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62) ... 参考: - RunWith helps JUnit « Pragmatic Programmer Issues – pietrowski.info -- http://pietrowski.info/2008/08/runwith-helps-junit/ --- JUnit4.4 - 4.5と若干古いが、内部判定処理の詳細まで調査を進めている類似事例。 * 対処法 テストクラスの宣言に以下のアノテーションを付与する。 ... import org.junit.runner.RunWith; import org.junit.runners.JUnit4; ... @RunWith(JUnit4.class) public class FooTest extends TestCase { ... 上に挙げた "RunWith helps JUnit" の記事では "JUnit4ClassRunner.class" を使っているが、JUnit-4.8.1においてはdeprecatedにされている。JavaDocを調べたところ、4.8.1においては"org.junit.runners.JUnit4"を使うと良いようだ。 "org.junit.runners.BlockJUnit4ClassRunner" というのもあるが、JavaDocで Developers wanting to explicitly tag a class as a JUnit 4 class should use @RunWith(JUnit4.class), not, for example in JUnit 4.5, @RunWith(BlockJUnit4ClassRunner.class). とあるため、JUnit4.classの方を採用した。 以上の対処により、Eclipse, Maven 共に@Testアノテーションが認識されるようになった。 #navi_footer|Java|