Kotlin

プロジェクトとテスト

Kotlinのファイル分割、package、checkによる検証、Gradleでの自動テストを学びます。

対象:Kotlin 2系・JDK 17以降のJVMコンソールアプリを対象にします。Android専用のAPIは使いません。

01

2つのファイルへ分ける

まず外部ライブラリなしで検証します。新しい空のフォルダーに、次の2ファイルをUTF-8で保存してください。入門の関数、require、例外を使います。packageは所属する名前空間です。同じpackageの関数はそのまま呼び出せます。

Price.ktKOTLIN
package study
fun total(price: Int, count: Int): Int {
    require(price >= 0 && count >= 0) { "負の値は使えません" }
    return price * count
}
Main.ktKOTLIN
package study
fun main() {
    println(total(120, 3))
}
同じフォルダーで実行COMMAND
kotlinc Price.kt Main.kt -include-runtime -d study.jar
java -jar study.jar
実行結果OUTPUT
360
02

checkで結果を自動確認

check は条件がfalseならIllegalStateExceptionを投げます。通常の成功、0個、負の入力を確認するようMain.ktを置き換えます。Price.ktは直前のまま使います。

Main.kt(全体を置き換え)KOTLIN
package study
fun main() {
    check(total(120, 3) == 360)
    check(total(120, 0) == 0)
    var rejected = false
    try {
        total(120, -1)
    } catch (error: IllegalArgumentException) {
        rejected = true
    }
    check(rejected)
    println("3項目の確認に成功しました")
}
再コンパイルして実行COMMAND
kotlinc Price.kt Main.kt -include-runtime -d study.jar
java -jar study.jar
実行結果OUTPUT
3項目の確認に成功しました

360を361へ変えるとcheckで停止します。元に戻して再実行しましょう。JVMのassertは実行オプションによって無効になるため、ここでは常に評価するcheckを使います。

03

Gradleプロジェクトへ進む

テストが増えたらGradleとテストフレームワークで管理します。IntelliJ IDEAで新しいKotlin/JVMプロジェクトを作り、ビルドシステムにGradle、DSLにKotlin、JDKに17以降を選びます。Gradle Wrapperを生成する設定を使ってください。

生成されたpluginsのKotlinバージョン指定は残します。build.gradle.ktsに、以下のブロックがなければ追加し、あれば内容を統合します。同じ設定を重複して追加しないでください。この例ではJUnit 5.11.4のBOMでJUnit関連のバージョンを揃え、engineでテストを実行します。

build.gradle.kts(該当ブロックへ統合)KOTLIN
repositories {
    mavenCentral()
}
dependencies {
    testImplementation(platform("org.junit:junit-bom:5.11.4"))
    testImplementation(kotlin("test-junit5"))
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
tasks.test {
    useJUnitPlatform()
}

Gradleの同期を実行します。Price.ktを src/main/kotlin/study/Price.kt に置きます。ここではcheck用のMain.ktは移さず、次のテストを src/test/kotlin/study/PriceTest.kt に新規保存します。生成時のサンプルテストはこの練習のテストに置き換えます。

04

テストを分けて実行

@Test がテストの目印です。assertEqualsは期待値と実際の値を比較し、assertFailsWithは指定した例外が投げられることを確認します。

src/test/kotlin/study/PriceTest.ktKOTLIN
package study
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

class PriceTest {
    @Test fun normalTotal() {
        assertEquals(360, total(120, 3))
    }
    @Test fun zeroCount() {
        assertEquals(0, total(120, 0))
    }
    @Test fun rejectsNegativeCount() {
        assertFailsWith<IllegalArgumentException> { total(120, -1) }
    }
}
macOS・Linux:プロジェクト直下で実行COMMAND
./gradlew test
Windows PowerShell:プロジェクト直下で実行COMMAND
.\gradlew.bat test
確認する結果OUTPUT
3つのテストが成功する
通常は最後にBUILD SUCCESSFULが表示される

Gradle Wrapperがない場合は、IDEで生成したプロジェクトか確認してください。初回は依存ライブラリをダウンロードします。レポートは通常 build/reports/tests/test/index.html に作成されます。

05

練習:価格0と負の価格

PriceTestへ価格0のテストと負の価格のテストを追加してください。次は追加後のPriceTest.kt全体です。

解答例を確認する
src/test/kotlin/study/PriceTest.kt(全体を置き換え)KOTLIN
package study
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

class PriceTest {
    @Test fun normalTotal() { assertEquals(360, total(120, 3)) }
    @Test fun zeroCount() { assertEquals(0, total(120, 0)) }
    @Test fun rejectsNegativeCount() {
        assertFailsWith<IllegalArgumentException> { total(120, -1) }
    }
    @Test fun freeProduct() { assertEquals(0, total(0, 3)) }
    @Test fun rejectsNegativePrice() {
        assertFailsWith<IllegalArgumentException> { total(-1, 3) }
    }
}
確認する結果OUTPUT
テストを再実行すると5テストが成功する

共有するのはソース、テスト、Gradle設定、Wrapperです。buildと.gradleは通常生成物として除外します。次にAndroidアプリへ進むときは、ここで覚えた言語とテストの基礎に画面作成を積み重ねましょう。

公式ドキュメントで確認する:JVMのテスト入門