Android フレームワーク依存のコードでユニットテストを行う方法
Android におけるテストの種類
Android には大きく分けて2種類のテストが存在します。
-
ローカル単体テスト(ユニットテスト)
- 実機やエミュレーターを使わず、Android Studio で実行できるテスト
- Android フレームワークに依存するコードが含まれない場合は基本的にこちらを選択する
-
インストルメンテーションテスト
- 実機やエミュレーターを使って行うテスト
- Android フレームワークに依存するコードもテストできる
- 本番に近い環境のテストなので信頼性は高いが、手間もかかる
下の画像は UnitTestSample プロジェクトを新規作成したときのディレクトリ構造です。com.example.unittestsample (androidTest)
にはインストルメンテーションテスト、com.example.unittestsample (test)
にはユニットテストのファイルを保存するようになっています。
Gladle ファイルに依存関係を追記するときもテストタイプが関わってくるので注意が必要です。ライブラリを androidTestImplementation
で記述してしまうと、ユニットテスト環境では使えません(私はこれでハマりました)。
dependencies {
...
// すべて環境で使用可能
implementation '...'
// ユニットテストの環境でのみ使用可能
testImplementation '...'
// インストルメンテーションテストの環境でのみ使用可能
androidTestImplementation '...'
...
}
ユニットテストで Android フレームワーク依存のコードをテストする
初期状態では Android フレームワーク依存のコードをユニットテストで動かすことはできません(例えば Context を使う関数のテストなど)。これを機能させるために Robolectric を利用します。Robolectric を使うことで JVM 上に Android 環境をシミュレートできるようになるので、テストのためにビルドしたり端末やエミュレーターを起動する必要がなくなります。
さっそく Robolectric のライブラリを追加します。
dependencies {
...
testImplementation "org.robolectric:robolectric:4.5.1"
}
testOptions
にも次の記述を追加します。
android {
...
testOptions {
unitTests.includeAndroidResources = true
}
}
これで Robolectric が使えるようになりました。
プロジェクトを作成したときサンプルとして作られる ExampleUnitTest にテストを書いてみます。
@Config(sdk = [28]) // エラー回避のため
@RunWith(RobolectricTestRunner::class) // Robolectric で実行
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
// 以下のテストを追加
@Test
fun appName_isCorrect() {
val context = InstrumentationRegistry.getInstrumentation().context
val appName = context.getString(R.string.app_name)
assertEquals(appName, "UnitTestSample")
}
}
この状態で appName_isCorrect
の左側にある ▶︎ から Run 'appName_isCorrect()'
を選択してテスト実行します。Robolectric のおかげで Context が機能して appName が取得できるようになり、テストが成功するかと思います。
1行目に @Config(sdk = [28])
を追記していますが、これが無いと以下のエラーが発生したため、Android SDK のバージョンを指定しています。
ava.lang.UnsupportedOperationException: Failed to create a Robolectric sandbox: Android SDK 30 requires Java 9 (have Java 8)
AndroidJUnit4 でテストをより快適にする
先ほどはテストランナーに RobolectricTestRunner を指定しましたが、AndroidJUnit4 を使うと、テストのタイプによって自動的にテストランナーを切り替えてくれるようになります。インストルメンテーションテストの場合は AndroidJUnit4 ランナー(Android 環境の標準ランナー)を使用し、ユニットテストの場合は RobolectricTestRunner を使用します。
また、Context などの Android フレームワークへのアクセス方法もインストルメンテーションテストとユニットテストで共通なので、AndroidJUnit4 を使えばテストのタイプを意識することなく同じ内容のテストが書けるようになります。
それでは AndroidJUnit4 を使うために以下のライブラリを追加します。
testImplementation 'androidx.test.ext:junit:1.1.2'
そして AndroidJUnit4 をテストランナーに指定します。
@Config(sdk = [28])
@RunWith(AndroidJUnit4::class)
class ExampleUnitTest {
...
}
もう一度テストを実行すると、問題なくテストが通るのを確認できるかと思います。
まとめ
- Android にはユニットテストとインストルメンテーションテストの2種類のテストがある
- ユニットテストで Android フレームワークのコードを書きたい場合は Robolectric を使おう
- AndroidJUnit4 を使うと2種類のテストを意識することなくテストが書けるのでより快適!
Author And Source
この問題について(Android フレームワーク依存のコードでユニットテストを行う方法), 我々は、より多くの情報をここで見つけました https://qiita.com/u-dai/items/cd7bba8c9bfe13bf0a91著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .