[Android] GitHub ActionsでRoom / Realmの自動テスト
目次
この記事はフラー株式会社 Advent Calendar 2021の25日目の記事です。
24日目の記事は @su8
さんによる「コンテナ遠洋航海 ~そこらへんの草でも食わせておけ プロセス分離の旅路 ~ - Qiita」でした。
Androidのローカルデータベースアクセスの自動テスト
2021年現在、Androidアプリ開発でローカルデータベース(SQLite)にデータを保存する場合は、Roomを使用することが多いと思います。数年前はRealmが流行っていたので、今もRealmを使用しているというプロジェクトも多いと思います。この記事では、RoomとRealmを用いたローカルデータベースアクセスの自動テストをGitHub Actionsで行う方法について書きます。
Roomのテスト
Roomのテストは、Dao単位で行うことを想定します。Roomのインメモリデータベースを用いてテストを行います。エミュレータテストになるので、 androidTest
にテストを書きます。
本記事の例では、Contextの取得に androidx.test.core.app.ApplicationProvider
を、テストランナーとして androidx.test.ext.junit.runners.AndroidJUnit4
を使用します。
setup
と tearDown
までは以下のように書けます。ここで、AwesomeDaoはRoomのDao、DatabaseはRoomDatabaseのサブクラスです。 setup
でインメモリデータベースをビルドした後、テストのtargetとなるDaoを作ります。 tearDown
では、データベースをcloseしています。
@RunWith(AndroidJUnit4::class)
class AwesomeDaoTest {
private lateinit var target: AwesomeDao
private lateinit var database: Database
@Before
fun setup() {
val context = ApplicationProvider.getApplicationContext<Context>()
database = Room
.inMemoryDatabaseBuilder(context, Database::class.java)
.setTransactionExecutor(StandardTestDispatcher().asExecutor())
.setQueryExecutor(StandardTestDispatcher().asExecutor())
.build()
target = database.awesomeDao()
}
@After
fun tearDown() {
database.close()
}
}
ここまでの準備ができたらあとはテストケースを書けば良いのですが、特にどうということもないので省略します。テストは gradlew connectedAndroidTest
などのコマンドから実行することができます。実際には、Build Variantsを適切に設定してください。
Realmのテスト
Roomと同様に、RealmのテストもRealmの提供するインメモリデータベースを用いてテストを行います。Realmのインメモリデータベースのインスタンスは、以下のように作成することができます。
RealmConfiguration.Builder()
.inMemory()
.name("your_name_here")
.build()
データベースアクセスを行うクラスにこのRealmのインスタンスをDIできるようにしておけば、Realmを用いたデータベースアクセスのテストを書くことができます。やっていることはRoomのテストと同様です。
class AwesomeDataSourceTest {
private lateinit var target: AwesomeDataSource
private var realm: Realm? = null
@Before
fun setup() {
val config = RealmConfiguration.Builder()
.inMemory()
.name("your_name_here")
.build()
realm = Realm.getInstance(config)
target = AwesomeDataSource(requireNotNull(realm))
}
@After
fun tearDown() {
realm?.close()
realm = null
}
}
GitHub Actions
ここまでできれば、あとはGitHub Actionsでトリガーが引かれた時にテストを実行するだけです。Instrumented Testにする必要がありますが、GitHub Actions上でAndroidのエミュレータをセットアップするための素晴らしいアクション malinskiy/action-android
が存在しますので、こちらを使えば苦労はいりません。
なお、エミュレータテストのために、OSとしてMacを選択する必要があることに注意してください(Ubuntuを使用する場合に比べて10倍の速度でお金が溶けます)。
以下は簡単なGitHub Actionsのワークフローのサンプルです。参考のため、Build Variantsを DevDebug
に設定しています。
jobs:
test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Set Up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '11'
- uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Install Android SDK
uses: malinskiy/action-android/install-sdk@release/0.1.2
- name: Instrumented Test
uses: malinskiy/action-android/emulator-run-cmd@release/0.1.2
with:
cmd: ./gradlew connectedDevDebugAndroidTest
api: 28
tag: default
abi: x86
以上で、Room / Realmの自動テストをGitHub Actions上で実行することができました。
まとめ
2019年、2020年に続き、2021年もフラー Advent Calendarの最終日を務めさせていただきました。来年も最終日を狙って参ります。よろしくお願いいたします。
#Android #GitHub Actions #Test
書いている人 😎

茨城県つくば市在住のモバイルアプリケーションアーキテクト(Androidが得意です)。モバイルアプリのアーキテクチャ、自動テスト、CI/CDに興味があります。いわゆる「レガシーコード」のリファクタリング・リアーキテクチャが好きです。
👉 もっと詳しく
著書 ✍
Android 依存性注入 ヒッチハイク・ガイド🧳
Androidアプリでの依存性注入(Dependency Injection)に入門するためのガイダンスです。依存性注入の概念やメリットを理解し、Dagger Hiltを用いてAndroidアプリに適用する方法を解説しています。
ソフトウェアデザイン 2023年6月号📚
特集「クリーンアーキテクチャとは何か?」の第5章「モバイルアプリ開発における実践」を執筆しました。
Android クリーンアーキテクチャ ヒッチハイク・ガイド🧳
Androidアプリでのクリーンアーキテクチャに入門するためのガイダンスです。クリーンアーキテクチャの概念を理解し、Androidアプリに適用する方法を解説しています。
Android ユニットテスト ヒッチハイク・ガイド🧳
Androidアプリのユニットテストに入門するためのガイダンスです。初学者が混乱せずにAndroidアプリのユニットテストを書き始めることができる、ということを目的としています。
Android MVVMアーキテクチャ入門🛠
Androidアプリ開発の初学者に向けた、MVVM(Model-View-ViewModel)アーキテクチャの入門書を書きました。初学者の方を確実にネクストレベルに引き上げる技術書です。NextPublishingより出版されています。
関連記事 👀
- GitHub ActionsでSonarCloudにカバレッジをアップロードする
- GitHub ActionsでktlintとAndroid Lintを並列実行して、DangerでPRにまとめてコメントする🐝
- Truthのカスタムサブジェクトを定義する
- Mockk によるモック入門
- Truth によるアサーション入門