日々常々

ふつうのプログラマがあたりまえにしたいこと。

junit-4.11.jar が単独で使えない

寂しがりだから Hamcrest と一緒に使ってあげてね。

やってみる

こんな風に書いて。

import org.junit.*;
import static org.junit.Assert.*;

public class HogeTest {

  @Test
  public void hoge() {
    fail("しぱーい");
  }
}


こうして。

$ javac -cp junit-4.11.jar HogeTest.java
$ ls
HogeTest.class		HogeTest.java		junit-4.11.jar


だーん。

$ java -cp ./junit-4.11.jar:. junit.textui.TestRunner HogeTest
.F
Time: 0.003
There was 1 failure:
1) warning(junit.framework.TestSuite$1)junit.framework.AssertionFailedError: No tests found in HogeTest

FAILURES!!!
Tests run: 1,  Failures: 1,  Errors: 0

$ 

……?
あ、間違えた。(junit.textui.TestRunner は昔の。)


こうだー!

$ java -cp junit-4.11.jar:. org.junit.runner.JUnitCore  HogeTest
JUnit version 4.11
Exception in thread "main" java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
	at org.junit.runner.Computer.getSuite(Computer.java:28)
(以下略)

てことでhamcrestが無いとJUnit動きません。


junit-dep-4.10.jar でも一緒。

$ java -cp junit-dep-4.10.jar:. org.junit.runner.JUnitCore  HogeTest
JUnit version 4.10
Exception in thread "main" java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
(以下略)


junit-4.10.jar ならいけます。

irof@Airof JUnit$ java -cp junit-4.10.jar:. org.junit.runner.JUnitCore  HogeTest
JUnit version 4.10
.E
Time: 0.014
There was 1 failure:
1) hoge(HogeTest)
java.lang.AssertionError: しぱーい
	at org.junit.Assert.fail(Assert.java:93)

原因

この子。

public class AssumptionViolatedException extends RuntimeException implements SelfDescribing {

org.junit.internal にあるけど org.hamcrest.SelfDescribing で、こいつを org.junit.runners.ParentRunner さんが使っちゃってる。だので ParentRunner を extends する Suite の無名クラスインスタンスを生成しようとしている Computer.getSuite でコケてる。

なんでJUnit4.11で?

4.10なら動いてたのに4.11で動かなくなったように見えるわけです。

junit-4.11.jar ×
junit-4.10.jar
junit-dep-4.10.jar ×

実際は4.11から junit-4.xx.jar が無くなって junit-dep-4.xx.jar だけになった感じ。

Maven artifacts

Up until now there were two Maven artifacts for JUnit: junit:junit-dep and junit:junit. From a Maven point-of-view only the former made sense because it did not contain the Hamcrest classes but declared a dependency to the Hamcrest Maven artifact. The latter included the Hamcrest classes which was very un-Maven-like.

junit/doc/ReleaseNotes4.11.md

要約すると「Gradle使え」です(書いてない)。

GradleでEclipseでJUnit4.11を使いたいとき

jarをダウンロードしてクラスパスに追加して……と、手作業で依存関係を管理する時代はもう終わってます。なのでGradleでやりましょう。

apply plugin: 'java'
apply plugin: 'eclipse'
repositories.mavenCentral()
dependencies.testCompile 'junit:junit:4.11'

……と build.gradle に書いて。


どーん。

$ gradle ec
:eclipseClasspath
:eclipseJdt
:eclipseProject
:eclipse

BUILD SUCCESSFUL

Total time: 9.286 secs

これで junit-4.11.jar と hamcrest-core-1.3.jar をダウンロードしてきて、Eclipse用の .classpath, .project, .settings/org.eclipse.jdt.core.prefs が出来るから、あとはインポートすればおk。


IntelliJ IDEA は Gradle をサポートしてるので、 build.gradle を開くだけでいいです。