✨
Gradle TestKitに触れてみる
背景
- DroidKaigi2025で@RyuNen344さんのGradleのセッションを聴いた。
- Gradleを雰囲気で書きがちなのでユニットテストなりで検証可能な形でタスクを組めると嬉しいなーと思いポストしたところ、テストフレームワーク自体は普通にあるらしいことを教えていただいた。
- せっかくなので触れてみる。
資料
触れてみた
1. 環境設定
- IntelliJ IDEAで新規プロジェクトを作成する。
- gradleTestKit() を依存に追加する。
dependencies {
...
testImplementation(gradleTestKit())
}
- テストフレームワークの依存がなければ適当に追加する。
- 新規プロジェクト作成だとデフォルトでJUnit5などが使える状態になっているような気がする。
2. サンプル写経 (in Kotlin/kts)
-
サンプルのテストコードはJavaで書かれているのでKotlin/ktsで書き直す。
-
書き直した結果は以下。
- @TempDirのディレクトリ下にファイルを書き出してGradleRunnerでビルドするのがポイントらしい。
- 実際に使うktsをcopyしてきてビルドを実行する、みたいなやり方もできなくはなさそう。
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class BuildLogicFunctionalTest {
@TempDir lateinit var testProjectDir: File
private lateinit var settingsFile: File
private lateinit var buildFile: File
@BeforeEach
fun setup() {
settingsFile = File(testProjectDir, "settings.gradle.kts")
buildFile = File(testProjectDir, "build.gradle.kts")
}
@Test
fun testHelloWorldTask() {
settingsFile.writeText("rootProject.name = \"hello-world\"")
val buildFileContent = """
task("helloWorld") {
doLast {
println("Hello, World!")
}
}
""".trimIndent()
buildFile.writeText(buildFileContent)
val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments("helloWorld")
.build()
assertTrue(result.output.contains("Hello, World!"))
assertEquals(TaskOutcome.SUCCESS, result.task(":helloWorld")?.outcome)
}
}
3. ファイル出力のテスト
- タスク外で定義したプロパティを入力としてtxtファイルを出力するタスクのテスト。
- こういうテストを書くならDefaultTask継承でタスクを書くほうがいい気がしてきた。
- キャッシュのテストもできるらしいが今後の宿題とする。
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class CalculateSumOfRangeTest {
@TempDir
lateinit var testProjectDir: File
private lateinit var buildFile: File
@BeforeEach
fun setup() {
buildFile = File(testProjectDir, "build.gradle.kts")
}
@Test
fun testCalculateSumOfRangeTask() {
val buildFileContent = """
val rangeMax = 100
task("calculateSumOfRange") {
inputs.property("rangeMax", rangeMax)
val outputFile = file("result.txt")
outputs.file(outputFile)
doLast {
println("Calculating...")
val sum = (1..rangeMax).sum()
val result = "Sum from 1 to ${'$'}rangeMax is ${'$'}sum"
println(result)
outputFile.writeText(result)
}
}
""".trimIndent()
buildFile.writeText(buildFileContent)
val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments("calculateSumOfRange")
.build()
assertTrue(result.output.contains("Calculating..."))
assertTrue(result.output.contains("Sum from 1 to 100 is 5050"))
assertEquals(TaskOutcome.SUCCESS, result.task(":calculateSumOfRange")?.outcome)
val outputFile = File(testProjectDir, "result.txt")
assertTrue(outputFile.exists())
assertEquals("Sum from 1 to 100 is 5050", outputFile.readText())
}
}
感想
- Gradleのテストを書くのは割と簡単そう。
- TaskやBuildResultへの理解を深めるともう少し捗りそう。
Discussion