概要
Java のテスティングフレームワーク JUnit は今年メジャーバージョンの 5 がリリースされます。先日 San Jose で開催されていた Eclipse Converge 2017 というカンファレンスで、この JUnit 5 を Eclipse で使う方法を聞いてきたので、Windows 10 の私物 PC で試してみました。
JUnit 5
JUnit の5番目のメジャーバージョンです。Java 8 や 9 での新しい言語仕様に対応するため、作り直したとのことです。
JUnit 4 でカバーしきれなかった新しい言語仕様
- Lambda expression
- Stream API
- Jigsaw
参考
JUnit 5 での新機能や注意点については、日本語でもすでに多数の資料が存在していますので、そちらをご参照ください。
環境
JUnit 5 は Eclipse 4.7.0(Oxygen) の Milestone 6 からβサポートするとのことでした。下記からダウンロードできます。
なお、この記事を書いている 2017/04/05 時点では 4.7.x の日本語化プラグインはないようです。
その他の環境は下記の通りです。
OS | Windows 10 |
---|---|
Java SE | 1.8.0_121 |
Eclipse | 4.7.0-M6 |
git | 2.12.2.windows.1 |
導入
JUnit 5 用の Eclipse プラグインをソースコードから作成して、お使いの Eclipse(4.7系)にインストールします。
https://wiki.eclipse.org/JDT_UI/JUnit_5 の手順に従い進めます。なお、ファイルのダウンロードに git が必要です。もちろん Eclipse もいります。Eclipse は Java のものをダウンロードしていれば特に問題はないと思います。"for Testers" をダウンロードしていた場合はプラグイン開発ツールを別途インストールしておいてください。
プラグインのビルドは Eclipse で実施するため、Ant や Maven や Gradle は不要です。
プラグイン開発用ワークスペースの準備
必須ではありませんが、まあ、通常の開発用ワークスペースと混ぜたくないと思いますので用意しておくとよいでしょう。
https://github.com/noopur2507/eclipse-junit5.git をチェックアウト
特にファイルのビルドは必要ないので、 https://github.com/noopur2507/eclipse-junit5/archive/master.zip をダウンロードしてくればよいです。その場合、eclipse-junit5-master.zip
というファイルがダウンロードされます。この zip ファイルの中身は、それぞれ下記の通り import & 配置してください。
- org.eclipse.jdt.junit5.runtime をプラグイン開発用ワークスペースに import
- JUnit-5-JARs の jar を dropins に配置
JUnit-5-JARs の jar を dropins に配置
git://git.eclipse.org/gitroot/jdt/eclipse.jdt.ui.git を clone する
git を使って clone してください。特に鍵の設定は要りません。なお、全部ダウンロードするのに10分以上かかります。
$ git clone git://git.eclipse.org/gitroot/jdt/eclipse.jdt.ui.git
Cloning into 'eclipse.jdt.ui'...
remote: warning: ignoring extra bitmap file: objects/pack/pack-dffcdea022429c2393e25dfe14e4b833fb5d7dd0.pack
remote: Counting objects: 474929, done.
remote: Compressing objects: 100% (715/715), done.
remote: Compressing objects: 100% (715/715), done.
remote: Total 474929 (delta 364), reused 0 (delta 0)
Receiving objects: 100% (474929/474929), 73.43 MiB | 125.00 KiB/s, done.
Resolving deltas: 100% (249502/249502), done.
Checking out files: 100% (12727/12727), done.
clone し終わったら移動してください。
$ cd eclipse.jdt.ui
BETA_JUNIT5 ブランチに切り替え
eclipse.jdt.ui $ git checkout -b BETA_JUNIT5
Switched to a new branch 'BETA_JUNIT5'
origin の BETA_JUNIT5 を pull
eclipse.jdt.ui $ git pull origin BETA_JUNIT5
From git://git.eclipse.org/gitroot/jdt/eclipse.jdt.ui
* branch BETA_JUNIT5 -> FETCH_HEAD
Auto-merging org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/JunitPreferenceInitializer.java
Merge made by the 'recursive' strategy.
org.eclipse.jdt.junit.core/plugin.properties | 3 +-
org.eclipse.jdt.junit.core/plugin.xml | 13 +-
.../jdt/internal/junit/JUnitCorePlugin.java | 5 +-
.../eclipse/jdt/internal/junit/JUnitMessages.java | 10 +-
.../jdt/internal/junit/JUnitMessages.properties | 6 +-
.../internal/junit/JUnitPreferencesConstants.java | 38 ++-
.../internal/junit/JunitPreferenceInitializer.java | 24 +-
.../internal/junit/buildpath/BuildPathSupport.java | 90 ++++++-
.../junit/buildpath/JUnitContainerInitializer.java | 59 ++++-
.../internal/junit/launcher/JUnit5TestFinder.java | 286 ++++++++++++++++++++
.../JUnitLaunchConfigurationConstants.java | 5 +-
.../internal/junit/launcher/TestKindRegistry.java | 12 +-
.../internal/junit/model/ITestRunListener2.java | 16 +-
.../eclipse/jdt/internal/junit/model/IXMLTags.java | 16 +-
.../junit/model/RemoteTestRunnerClient.java | 2 +-
.../jdt/internal/junit/model/TestCaseElement.java | 12 +-
.../jdt/internal/junit/model/TestElement.java | 55 +++-
.../eclipse/jdt/internal/junit/model/TestRoot.java | 4 +-
.../jdt/internal/junit/model/TestRunHandler.java | 14 +-
.../jdt/internal/junit/model/TestRunSession.java | 107 ++++++--
.../junit/model/TestRunSessionSerializer.java | 28 +-
.../jdt/internal/junit/model/TestSuiteElement.java | 12 +-
.../internal/junit/util/CoreTestSearchEngine.java | 60 ++++-
.../src/org/eclipse/jdt/junit/JUnitCore.java | 10 +-
.../launcher/JUnitLaunchConfigurationDelegate.java | 107 ++++++--
org.eclipse.jdt.junit.runtime/META-INF/MANIFEST.MF | 8 +-
.../junit/runner/FirstRunExecutionListener.java | 4 +-
.../jdt/internal/junit/runner/ITestIdentifier.java | 5 +-
.../jdt/internal/junit/runner/ITestLoader.java | 5 +-
.../internal/junit/runner/IVisitsTestTrees.java | 4 +-
.../jdt/internal/junit/runner/MessageIds.java | 24 +-
.../internal/junit/runner/RemoteTestRunner.java | 81 ++++--
.../jdt/internal/junit/runner/TestIdMap.java | 2 +-
.../junit/runner/TestReferenceFailure.java | 7 +-
.../junit/runner/junit3/JUnit3Identifier.java | 10 +-
.../junit/runner/junit3/JUnit3TestLoader.java | 4 +-
.../junit/runner/junit3/JUnit3TestReference.java | 22 +-
org.eclipse.jdt.junit/plugin.xml | 11 +-
.../junit/buildpath/JUnitContainerWizardPage.java | 19 +-
.../junit/ui/JUnitClasspathFixProcessor.java | 38 ++-
.../jdt/internal/junit/ui/JUnitMessages.java | 12 +-
.../jdt/internal/junit/ui/JUnitMessages.properties | 10 +-
.../eclipse/jdt/internal/junit/ui/JUnitPlugin.java | 53 +++-
.../internal/junit/ui/JUnitQuickFixProcessor.java | 47 +++-
.../junit/ui/JUnitUIPreferencesConstants.java | 18 +-
.../jdt/internal/junit/ui/OpenTestAction.java | 30 ++-
.../jdt/internal/junit/ui/TestRunnerViewPart.java | 21 +-
.../junit/ui/TestSessionLabelProvider.java | 45 ++--
.../eclipse/jdt/internal/junit/ui/TestViewer.java | 152 ++++++++---
.../jdt/internal/junit/util/JUnitStubUtility.java | 8 +
.../junit/wizards/NewTestCaseCreationWizard.java | 69 +++--
.../junit/wizards/SuiteClassesContentProvider.java | 4 +-
.../jdt/internal/junit/wizards/WizardMessages.java | 7 +-
.../junit/wizards/WizardMessages.properties | 9 +-
.../launcher/JUnitLaunchConfigurationTab.java | 27 +-
.../jdt/junit/launcher/JUnitLaunchShortcut.java | 48 ++--
.../junit/wizards/NewTestCaseWizardPageOne.java | 290 ++++++++++++++++-----
.../jdt/junit/wizards/NewTestSuiteWizardPage.java | 4 +-
.../internal/junit4/runner/JUnit4Identifier.java | 10 +-
.../internal/junit4/runner/JUnit4TestLoader.java | 3 +-
.../junit4/runner/JUnit4TestReference.java | 6 +-
.../corext/codemanipulation/StubUtility.java | 2 +-
.../templates/default-templates.properties | 4 +-
org.eclipse.jdt.ui/templates/default-templates.xml | 15 +-
64 files changed, 1728 insertions(+), 404 deletions(-)
create mode 100644 org.eclipse.jdt.junit.core/src/org/eclipse/jdt/internal/junit/launcher/JUnit5TestFinder.java
こちらのコードもMaven等のビルドツールでビルドする必要はありません。更新されたフォルダ群から、下記5つをプラグイン開発用ワークスペースに import してください。
- org.eclipse.jdt.ui
- org.eclipse.jdt.junit
- org.eclipse.jdt.junit.core
- org.eclipse.jdt.junit.runtime
- org.eclipse.jdt.junit4.runtime
プラグインのエクスポートとインストール
Eclipse のメニューバーから「ファイル」→「エクスポート」→「プラグイン開発(Plug-in Development)」の "Deployable plug-ins and fragments" を選択します。当然ですが、プラグイン開発ツールが入っていないと選択肢が出てきません。Test Developer 版を入れている場合は注意してください。
"Install into host. Repository:" under "Destination" チェックボックスにチェックを入れている場合、プラグインのエクスポートが終了次第、続けてプラグインのインストールを始めます。インストールが終わると Eclipse が再起動を求めてくるので再起動しましょう。
Windows の場合、もし Eclipse を C ドライブに置いていてランチャーが消えてしまった場合は、手間ですが再度 Eclipse をダウンロードして exe ファイルだけを eclipse フォルダにコピーしましょう。
確認
新規の Java プロジェクトを作成し、ビルドパスの設定を開いて、ライブラリの追加で JUnit を選択します。プラグインが正常にエクスポート&インストールされていれば、ここで出るダイアログの選択肢に JUnit 5 が追加されているはずです。
これで Eclipse 上で JUnit 5 の開発ができるようになりました。
JUnit 5 を愉しむ
では、試しに JUnit 5 のコードを書いて動かしてみましょう。今回は JUnit 5 の新機能 Group assertion を試すコードを書いてみます。
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class BaseTest {
@Test
public void test() {
Assertions.assertEquals(Integer.valueOf(1).toString(), "1");
Assertions.assertAll(
() -> Assertions.assertEquals(Integer.valueOf(1).toString(), "1"),
() -> Assertions.assertEquals(Integer.valueOf(1).toString(), "2"),
() -> Assertions.assertEquals(Integer.valueOf(3).toString(), "3"),
() -> System.out.println("Hello JUnit5!")
);
}
}
JUnit 4 までと同じように動かせます。
はい、2番目の Assertion が fail なのでテストは失敗します。ここで注目してほしいのは、コンソールに "Hello JUnit5!" と出力されている点です。従来の JUnit では、1つのテストメソッド内で assertion が fail した場合、以降の処理は一切実行されませんでした。JUnit 5 の Group assertion では、その Group 内の処理は必ず実行されるようになっています。
これで、今回エクスポートした JUnit 5 用プラグインが正常に動作することを確認できました。ここまで3時間ほどかかりました。
まとめ
まだ結構面倒ですので、業務で JUnit 5 をプロジェクトに導入したいのであれば、よほどの理由がない限り、Eclipse が JUnit 5 に正式対応するまで待つか、IntelliJ を使いましょう……
あるいは、Gradle や Maven プラグイン経由で使うのが良いと思います。
参考
JUnit 5 User Guide
Eclipse Converge 2017 のセッション "Embracing JUnit 5 with Eclipse"
- セッション紹介:Embracing JUnit 5 with Eclipse
- 資料(PDF):Embracing JUnit 5 with Eclipse