📝

Android アプリに kotlin.test を導入した話

2023/03/10に公開

はじめに

ドワンゴ社のN予備校 Android アプリ開発チームに業務委託として参加している藤崎です。当アプリに kotlin.test を導入した話を紹介します。

N予備校アプリは 2016 年 4 月にリリースしたもので、当時は Java だけで書かれていました。現在に至り、使っているアサーションライブラリは JUnit と Hamcrest が混在していました。特に Hamcrest は Kotlin の予約語と関数名が衝突したりと煩雑になりがちでした。そこでテストの読み書きを改善するため、アプリで使うアサーションライブラリを見直すことにしました。

アサーションライブラリの選定

アサーションライブラリの選定にあたり重視したのは標準であることです。ライブラリには流行りすたりがあります。アサーションライブラリの使用箇所は広いことから、すたれる度に乗り換えるのは大変です。AndroidやKotlinに公式に推されているライブラリはすたれにくいという考えに基づき、Android 開発者向け公式サイト(developer.android.com)が推奨しているか Kotlin 公式のライブラリに絞りました。絞られたライブラリは以下の通りです。

  • JUnit
    • JUnit は総合的なユニットテストライブラリですが、今回は JUnit 内の Assert 系関数 を指しています。
  • Hamcrest
  • Truth
  • kotlin.test (Kotlin 公式)

※ developer.android.com で推奨されています。

We recommend you use an assertions library such as junit.Assert, Hamcrest, or Truth.

https://developer.android.com/training/testing/local-tests#test-class

上記4ライブラリから最も将来性のあるライブラリを選ぶにあたり、以下を考慮しました。

  • ライブラリの開発言語
    • どちらかと言えば Java より Kotlin の方が好ましい
  • ライブラリの主な開発者
    • どちらかと言えばコミュニティより実績のある企業の方が好ましい
  • Android公式の比較的新しい主要なオープンソースアプリで使われているか
  JUnit Hamcrest Truth kotlin.test
開発言語 Java Java Java Kotlin
主な開発者 コミュニティ コミュニティ Google JetBrains
github.com/android/nowinandroid ✖️ ✖️
github.com/android/compose-samples ✖️ ✖️ ✖️

JUnit と kotlin.test は甲乙つけ難いですが、あえてサードパーティ製を使う必要も無いかもしれないと思い、 kotlin.test を導入することにしました。

kotlin.test の導入

  1. kotlin.test へ移行したいモジュールの build.gradle.kts に以下を指定します。
testImplementation(kotlin("test")) // ユニットテストが無ければ不要
androidTestImplementation(kotlin("test")) // UIテストが無ければ不要
  1. 以下を参考に、JUnit や Hamcrest の記述を kotlin.test のそれに置き換えます。
  JUnit Hamcrest kotlin.test
@Test import org.junit.Test n/a import kotlin.test.Test
(実体は org.junit.test への typealias)
@Before または @BeforeTest import org.junit.Before n/a import kotlin.test.BeforeTest
(実体は org.junit.Before への typealias)
@After または @AfterTest import org.junit.After n/a import kotlin.test.AfterTest
(実体は org.junit.After への typealias)
@Ignore import org.junit.Ignore n/a import kotlin.test.Ignore
(実体は org.junit.Ignore への typealias)
assertTrue系 assertTrue(actual) assertThat(actual, `is`(true)) assertTrue(actual)
assertNull系 assertNull(actual) assertThat(actual, `is`(nullValue())) assertNull(actual)
assertIs系 assertTrue(actual is String) assertThat(actual, `is`(instanceOf(String::class.java))) assertIs<String>(actual)
assertEquals系 ※ assertEquals(expected, actual) assertThat(actual, `is`(expected)) assertEquals(expected, actual)
assertCollectionContains系 assertTrue(element in iterable) assertThat(iterable, hasItem(element)) assertContains(iterable, element)
assertStringContains系 assertTrue(substring in actual) assertThat(actual, containsString(substring)) assertContains(actual, substring)

※ 注意点として Hamcrest のassertThatではactualを第1引数に取るのに対し、kotlin.test の assertEqualsではactualを第2引数に取ります。

  1. 置き換えが完了したかどうかは、kotlin.test に置き換えられない以下を除き…
import org.junit.Rule
import org.junit.runner.RunWith

…以下が存在しないことです。

import org.junit.<>
import org.hamcrest.<>

kotlin.test の導入後1ヶ月経って

良かった点

  • 複数のライブラリ(JUnit と Hamcrest)の混在が解消され、テストコードの見通しが改善した。
  • kotlin.test の 各関数は Hamcrest よりも簡潔な一方で、JUnit と概ね同じなので学習コストはほとんどかからなかった。

悪かった点

悪かった点はまだありませんが、kotlin.test は同じ Kotlin 製テストライブラリ の Kotest と比べても機能は限定的で認知度も高くありません。これから利用者が増えることを期待します。

おわりに

今回は kotlin.test を導入した話を紹介しました。テストライブラリやテストコードを整備することは、テストを書く機運を高める上でも重要だと思っています。今回の話が kotlin.test に興味がある方々の参考になれば幸いです。

Discussion