2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Ateam Finergy Inc.× Ateam CommerceTech Inc.× Ateam Wellness Inc. Advent Calendar 2022 の14日目は株式会社エイチームウェルネス @yothio が担当します

レガシーなAndroidアプリ/最新のアーキテクチャを上手く追従できていないAndroidアプリを保守していこうと思った時「ロジックが正しいか」といったテストを書こうとしても、Viewとロジックが分離されていないことがあるためユニットテストを書き進めるのは難しく「見た目上変更がない」「アプリケーション全体で見た時に不具合が気づけるように」という思いの元、E2Eテストから先に作ってみようと思いました

初めに

最近Webばっかり書いていたのもあり「AndroidでのE2Eは難しそう、あんまりイメージがつかない」と漠然に思っていましたが、実際に触ってみると簡単にできたので「難しいと思って手を出したことがない人」に届くと嬉しく思います
:thinking: そもそもE2Eテストってなんだっけ?」といった
E2Eテスト自体については今回は省かせていただきます :pray:

Espressoの導入

Androidの公式にも書いてある通りのUIテストライブラリのEspressoを使用してE2Eテストを進めます
基本的には公式ドキュメントに書いてあるとおり進めますが一部非推奨のものなどあるので適宜変更していきます

導入の時にやることとしては

  1. ライブラリの追加
  2. テスト実行時のランナーの指定
  3. テストファイルとコードの作成

ライブラリの追加

Espressoのドキュメントに書かれている通りにtestInstrumentationRunnerの項目追加と下記のライブラリを追加します。
ただ、執筆時のEspressoのドキュメントではDeprecateになっているサンプルコードが存在するので、回避するたandroidx.test.ext:junit-ktxも追加します。

build.gradle(:app)
android {
    compileSdk 33

    defaultConfig {
        applicationId "com.example.e2etest"
        minSdk 26
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // <<<----- こちらがなければ追加
    }
    ....
}

dependencies {
  .....

  androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.3'
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
  androidTestImplementation 'androidx.test:runner:1.4.0'
  androidTestImplementation 'androidx.test:rules:1.4.0'
}

テストファイルの追加

プロジェクトの新規作成時にapp/src/androidTest/java/com/~~~とandroidTestのディレクトリが作成されているはずですがなければ作りましょう
作成したディレクトリにテストファイルを作成します
今回は例として下記の名前で作成しました
app/src/androidTest/java/com/example/e2etest/HelloEspressoTest.kt

テストコードの追加

Espressoのサンプルと基本的に同じですが、ActivityTestRuleがdeprecateとなっているのでactivityScenarioRuleに置き換えています。
こちらが先ほどライブラリ追加であったandroidx.test.ext:junit-ktxを追加する理由となります。

activityScenarioRule使用したテスト
package com.example.e2etest

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.rules.activityScenarioRule
import androidx.test.filters.LargeTest
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
@LargeTest
class HelloEspressoTest {

    @get:Rule
    val activityRule = activityScenarioRule<MainActivity>()

    @Test
    fun listGoesOverTheFold() {
        onView(withText("Hello world!")).check(matches(isDisplayed()))
    }
}

activityScenarioRuleについては「Espressoのサンプルコード」ではなく
↓の「アプリのアクティビティをテストする」にて使用されているのでこちらを参考する方が良いかも

テストを実行するためには、ActivityもしくはFragmentを起動する必要があります
そのためactivityScenarioRuleを使用してMainActivityを起動します
上記のサンプルコードのように@get:Ruleの対象としてactivityScenarioRuleを指定してますが
アクティビティの起動はテストメソッド内でlaunchActivityを実行しても同じ結果が得られます

launchActivity使用したテスト

@RunWith(AndroidJUnit4::class)
@LargeTest
class HelloEspressoTest {
    @Test
    fun listGoesOverTheFold() {
        launchActivity<MyActivity>()
        onView(withText("Hello world!")).check(matches(isDisplayed()))
    }
}

同一のファイル内に複数テストを書く場合はactivityScenarioRuleで書いておくと自動的にアクティビティが立ち上がるので基本的にそちらで良いと思います

テスト書いていく

これまでの手順でテストが動作するようになったので後は好きにE2Eを書いていくだけです
Espressoが提供しているメソッドを利用して、Viewの要素をViewInteractionとして取得し、その要素に対して検証していきます

サンプルコードの例だと
withTextにて「Hello World!」と表示しているViewを取得し
onViewでwithTextの時に取得したViewのViewInteractionを作成し、表示されているかを検証しています

onView(withText("Hello world!")) // Viewの要素を取得
  .check(matches(isDisplayed())) // 要素の検証

また、Viewの要素を取得できるためEditTextなら入力
ClickListenerを登録しているならクリックさせて要素を検証してあげると良いでしょう

onView(withId(R.id.button_first))
  .perform(click())

注意

さまざまな背景によって、

フラグメントは、特定の親アクティビティまたはフラグメントに依存してはなりません。

スマートフォンアプリに関わるのが久しぶりだったので誤っている箇所やより良い方法などあればコメントや編集リクエストをいただけると助かります

最後に

Android Developersに書かれていますがFragmentはActivityに依存しない設計で組んであれば全体を通してテストをせずにFragment単体でテストすることを推奨していますが

ActivityとFragmentの結合度が高くなっていたりと、上手く分離できていないケースがある場合はActivityを通じてE2Eテストを行い
テストが通る → リファクタリング → テストが通る → Viewとロジックの分離 → テストが通る → ... 」といったように徐々にシステムを変更していくと安全に改善していけるかと思います

サンプルと作成したコードはこちらのリポジトリに上げてるのでご参考ください
https://github.com/yothio/android-e2e-sample

またEspressoの公式ドキュメント下部にサンプルプロジェクトのリンクがあり、そちらのテストの方が大変参考になるため一度見てみると良いかと思います
https://github.com/android/testing-samples/tree/main/ui/espresso

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?