概要
Android で普通の Unit Test (Android Test/Instrument Test じゃない方のテスト) で R.string.xxx についての Assert を実行すると下記のような謎の数値のエラーになっちゃうんですよね。
テストコード
val actual = hoge.getTextId()
assertEquals(R.string.xxx, actual)
こうだしたいですよね:
expected:<R.string.xxx> but was:<R.string.yyy>
Expected:R.string.xxx
Actual :R.string.yyy
<Click to see difference>
java.jang ... (以下略)
ですが、AndroidTest でないと Resource にアクセスできないし、そもそもリソースのキー名は取れないし、ググっても方法見つからないし、難しい壁が立ちはだかってます。
ですが、方法あったんですね。
Reflection
で R.string
解析してしまえばいいんです。
具体的に説明します。
用意するクラス
TestBase.kt
import kotlin.reflect.*
abstract class TestBase {
fun assertResStringEquals(expected: Int, actual: Int) {
assertEquals(getResStringName(expected), getResStringName(actual))
}
companion object {
fun getResStringName(id: Int): String {
return resStringId2Name[id] ?: "$id"
}
private val resStringId2Name: Map<Int, String> = R.string::class.members
.filter { it.parameters.isEmpty() && it.visibility == KVisibility.PUBLIC }
.associate {
val name = it.name
val id = it.call() as Int
id to "R.string.$name"
}
}
}
これだけです。
テストクラス
実際のテストではこのように使います。
HogeTest.kt
class HogeTest : TestBase() {
@Test
fun hoge() {
val actual = hoge.getTextId()
assertResStringEquals(R.string.xxx, actual) // ここを変えただけ
}
}
これで理想通りにキーをベースにエラー出力されます!
簡単ですね!