Gradle 7.4 + JUnit 5.8.1でUnitテストとは別にIntegrationTestを作る

小ネタ。JUnitにて./gradlew testで実行するテスト(Unitテスト)とは別に複数の要素が絡む総合テスト(Integration Test)を動かしたいことがあります。今回はその実装方法について。

結論

早速結論です。build.gradleに以下のように書けば良いです。

sourceSets {
    integrationTest {
        java {
            compileClasspath += main.output + test.output
            runtimeClasspath += main.output + test.output
            srcDir file('src/intTest/java')
        }
        resources.srcDir file('src/intTest/resources')
    }
}

configurations {
    integrationTestImplementation.extendsFrom testImplementation
    integrationTestRuntime.extendsFrom testRuntime
}

task integrationTest(type: Test) {
    useJUnitPlatform()
    testClassesDirs = sourceSets.integrationTest.output.classesDirs  // DirではなくDirsにする
    classpath = sourceSets.integrationTest.runtimeClasspath
    outputs.upToDateWhen { false }
}

あとはsrc/intTest/java以下にIntegration Test用のテストプログラムを書き、

./gradlew clean integrationTest

を実行すればOKです。

調査の流れ

実装するために調査したところ、以下のブログがヒットしました。

inspeerity.com

上記のブログはGroovyの例なのですが、JavaでもsourceSetsを変えれば良いかなと思って始めました。こんな感じに書きました。

sourceSets {
    integrationTest {
        java {
            compileClasspath += main.output + test.output
            runtimeClasspath += main.output + test.output
            srcDir file('src/intTest/java')
        }
        resources.srcDir file('src/intTest/resources')
    }
}

テスト用のクラスパスを通すために以下の記述を追加。

configurations {
    integrationTestImplementation.extendsFrom testImplementation
    integrationTestRuntime.extendsFrom testRuntime
}

動かしたときにパッケージorg.junit.jupiter.apiは存在しませんみたいなエラーメッセージが出たら、上記の設定を見直すか、build.gradledependenciesに以下の記述があることを確認します。

dependencies {
    // 他のものは省略
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

最後にtaskの定義です。

task integrationTest(type: Test) {
    useJUnitPlatform()
    testClassesDirs = sourceSets.integrationTest.output.classesDirs  // DirではなくDirsにする
    classpath = sourceSets.integrationTest.runtimeClasspath
    outputs.upToDateWhen { false }
}

useJUnitPlatform()がないと./gradlew clean integrationTestを実行してもテストが実行されず、しばらくハマりました。

参考

理解を深めるための各種参考資料。