Home About
android, kotlin

Android Studio を使わない ライブラリプロジェクトで Robolectric テストをする一番簡単なプロジェクト例

諸事情により Android Studio を使わないでライブラリはつくるようにしています。 その場合の Junit4 と Robolectric を使った 一番簡単なテストの書き方を覚え書きとしてここに残します。

android-color というプロジェクト

com.example.color パッケージでつくる android-color というプロジェクトをサンプルとしてつくります。

はじめに、android-color というディレクトリを作成しておきます。 これがプロジェクトのルートディレクトリになります。

プロジェクトの全体像は以下の通り:

実行環境:

java

$ java -version
openjdk version "1.8.0_275"

gradle

$ gradle -version
------------------------------------------------------------
Gradle 6.5
------------------------------------------------------------
Kotlin:       1.3.72
Groovy:       2.5.11
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          1.8.0_275 (Private Build 25.275-b01)
OS:           Linux 4.15.0-128-generic amd64

Android SDK などは適宜セットアップ済みとします。

設定ファイル関係を確認

build.gradle

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'maven'

buildscript {
    ext.kotlin_version = '1.4.10'

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.0.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

android {
    compileSdkVersion 30

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    testOptions {
        unitTests {
            includeAndroidResources = true
        }
    }
}

repositories {
    google()
    jcenter()
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    testImplementation 'junit:junit:4.12'
    testImplementation 'org.robolectric:robolectric:4.4'
}

gradle.properties

android.useAndroidX=true

これを設定せずに実行すると:

Execution failed for task ':mergeDebugUnitTestResources'.
> This project uses AndroidX dependencies, but the 'android.useAndroidX' property is not enabled. Set this property to true in the gradle.properties file and retry.

とエラーになる。

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.color" />

robolectric.properties

sdk=28

Java8 環境では sdk=28 にする必要がある。

肝心のコード

ColorUtils.kt

テスト対象のコードです。

android.graphics.Color.alpha, red, gree, blue 相当のメソッドを kotlin で再実装したものです。

package com.example.color

object ColorUtils {
    fun alpha(color: Int): Int {
        return color ushr 24
    }

    fun red(color: Int): Int {
        return color shr 16 and 0xFF
    }

    fun green(color: Int): Int {
        return color shr 8 and 0xFF
    }

    fun blue(color: Int): Int {
        return color and 0xFF
    }
}

ColorUtilsTest.kt

ColorUtils.kt をテストするためのコード.

ColorUtils クラスが android.graphics.Color.alpha, red, gree, blue 相当のメソッドを kotlin で再実装したものであるため、 本物の Color.alpha, Color.red, Color.green, Color.blue メソッドと同じ値を返すかテストしています。

package com.example.color

import org.junit.Test
import org.junit.Assert
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import android.graphics.Color

@RunWith(RobolectricTestRunner::class)
class ColorUtilsTest {
    @Test
    fun test1(){
        val color = Color.argb(255, 128,64,32)

        val a0 = Color.alpha(color)
        val r0 = Color.red(color)
        val g0 = Color.green(color)
        val b0 = Color.blue(color)

        val expected = listOf(a0, r0, g0, b0).joinToString(",")

        val a1 = ColorUtils.alpha(color)
        val r1 = ColorUtils.red(color)
        val g1 = ColorUtils.green(color)
        val b1 = ColorUtils.blue(color)

        val actual = listOf(a1, r1, g1, b1).joinToString(",")

        Assert.assertEquals(expected, actual)
    }
}

以上です。 わかってしまえば簡単というか、これだけのことなんですが、ググっても情報に辿りつくことができず苦労しました。

まとめ

Android のクラスを含んだテストを実機なしでコマンドラインでテストできるのは便利です。 Robolectric はテスト時間がかかるにはかかるのですが、 コマンドラインだけでテストできるならば、速めのサーバ上で ssh 経由で行うなどすればよいかと。

ChromeOS では Android が動くわけだから、 ChromeOS 上での Android 開発時のテストが Robolectric なしでできるようになればいいのに。