

それでも Ant を使いたい人のための JUnit 5
こんにちは、ソリューション開発部の柴崎です。
本記事はアプレッソ Advent Calendar 第13日目の記事です。アプレッソ Advent Calendar に協力会社も参加しても良いとのことで、書かせていただきます! (2年連続2回目, 昨年の記事)
俺達は、Ant を……強いられているんだッ!
昨今 Ant をビルドに使うことも少ないかと思いますが、今現在も Ant 本体の保守・改修は続いていており、現場によってはまだまだ Ant が現役であることがあります。そんな Ant を使わざるをえないけれど JUnit 5 を使いたいというニッチな要望を満たすために、Console Launcher 使ってみました。以下のような build.xml となりましたのでご査収ください。
<?xml version="1.0" encoding="UTF-8" ?>
<project default="test" xmlns:if="ant:if">
<target name="test">
<!-- ANSI カラーに対応している場合に false にすると色付きの出力となります。 -->
<property name="disable.ansi.colors" value="true"/>
<!--
details オプションに tree を選択した場合の形式です。
ユニコードに対応している場合に unicode を指定すると見やすいシンボルが使われるようになります。
-->
<property name="details.theme" value="ascii"/>
<script language="javascript"><![CDATA[
if (java.nio.charset.Charset.defaultCharset().newEncoder().canEncode('✔')) {
project.setProperty('details.theme', 'unicode');
}
]]></script>
<!-- テスト対象を含むクラスパスです。 -->
<path id="test.class-path">
<pathelement location="path/to/test-classes"/>
</path>
<!--
テストレポートの出力先です。
Ant の JUnit タスクにおける <formatter type="xml" /> を指定した場合と同じ内容となります。
-->
<property name="reports.dir" value="path/to/reports-dir"/>
<java fork="true" classname="org.junit.platform.console.ConsoleLauncher">
<arg value="--disable-ansi-colors" if:true="${disable.ansi.colors}"/>
<arg line="--details tree"/>
<arg line="--details-theme ${details.theme}"/>
<arg value="--class-path"/>
<arg pathref="test.class-path"/>
<arg line="--scan-class-path"/>
<arg value="--reports-dir"/>
<arg value="${reports.dir}"/>
<classpath>
<fileset dir="path/to/lib">
<include name="*.jar"/>
<!--
junit-platform-console-standalone には
hamcrest-all が含まれていません。必要に応じて追加してください。
-->
</fileset>
</classpath>
</java>
</target>
</project>
なぜ Console Launcher を使うのか
Ant にJUnit タスクがありますが、残念なことに JUnit 5 に対応しておりません。Apache Ant 側でも JUnit 側でも対応するような動きがありません。
にある通り、Console Launcher を使うのがよさそうです。
補足
Console Launcher の入手方法や指定できるパラメータについては、以下の公式ドキュメントを参照してください。
ユニコードに対応している場合に –details-theme オプションに unicode を指定すると見やすいシンボルが使われるようになります。この記事では、ユニコードに対応しているかどうかを Script タスクで調べ対応している場合は有効にしています。
また Java タスクの には、入手した junit-platform-console-standalone を含めます。これには JUnit 5 および JUnit 4 を実行できるライブラリが含まれていますが、Java Hamcrest の hamcrest-all は含まれていません。テストで利用している場合は、あわせて含める必要があります。
JUnit 5 と JUnit 4 のテストコードを実行できるか確認する
前述の build.xml で test を実行すると、path/to/test-classes ディレクトリ以下のクラスファイルからテストを探しを実行します。今回は、JUnit 5 と JUnit 4 のテストコード両方を一緒にテスト実行してみます。
$ ant
Buildfile: /path/to/build.xml
test:
[java] ╷
[java] ├─ JUnit Jupiter ✔
[java] │ └─ JUnit5Test ✔
[java] │ ├─ successful() ✔
[java] │ ├─ error() ✘ 予期せぬXが発生しました
[java] │ └─ disabled() ↷ void ant.with.junit5.JUnit5Test.disabled() throws java.lang.Throwable is @Disabled
[java] └─ JUnit Vintage ✔
[java] └─ ant.with.junit5.JUnit4Test ✔
[java] ├─ failed ✘ xのはずなのにyでした
[java] ├─ successful ✔
[java] └─ ignored ↷
[java]
[java] Failures (2):
[java] JUnit Jupiter:JUnit5Test:error()
[java] MethodSource [className = 'ant.with.junit5.JUnit5Test', methodName = 'error', methodParameterTypes = '']
[java] => java.lang.RuntimeException: 予期せぬXが発生しました
[java] JUnit Vintage:ant.with.junit5.JUnit4Test:failed
[java] MethodSource [className = 'ant.with.junit5.JUnit4Test', methodName = 'failed', methodParameterTypes = '']
[java] => java.lang.AssertionError: xのはずなのにyでした
[java]
[java] Test run finished after 103 ms
[java] [ 4 containers found ]
[java] [ 0 containers skipped ]
[java] [ 4 containers started ]
[java] [ 0 containers aborted ]
[java] [ 4 containers successful ]
[java] [ 0 containers failed ]
[java] [ 6 tests found ]
[java] [ 2 tests skipped ]
[java] [ 4 tests started ]
[java] [ 0 tests aborted ]
[java] [ 2 tests successful ]
[java] [ 2 tests failed ]
[java]
[java] Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
[java] Java Result: 1
BUILD SUCCESSFUL
Total time: 1 second
見事に Ant から JUnit 5 と JUnit 4 両方のテストを実行することができました。
まとめ
Ant 本体側にコントリビュートするべきと思い、JUnitTask を見て isJUnit4 変数に歴史の重みを感じた結果、この記事の内容となりました。お察しください。
Ant の JUnit タスクすべてのパラメータをそのまま移行することはできないものの、本件の手法で過去のテストコードを残しつつ JUnit 5 のテストコードを Ant から実行できることがわかりました。Ant から JUnit 5 を使うというかなりニッチな内容で、今後公式に対応されるかもしれませんが、取り急ぎの対応として参考になれば幸いです。