お久しぶりです。くぎみやです。
問題発覚
AndroidKeyStore
を使っていて、 encrypt
して decrypt
できるかのテストを書こうと思いました。特にここら辺はHWも関わってくるところであるために、モックなど使わずにサボらずに実機 (or エミュレータ)でテストを書こうと思ったのが始まりでした。
encrypt
したものを decrypt
し、元のテキストになるかのテストを書き、 Android8.1のエミューレータで動かしたところ、テストはしっかり動きました。そして、いくつか修正して最終的に SUCCESS
の文字がターミナルにでて来ました。
いつもであればこれで良しとするのですが、 AndroidKeyStore
周りのAPIがAndroid6.0から結構変わっておりまして、そのためminSDKのバージョンに指定しているAndroid4.3でも試して見たところ問題が発生しました。
com.android.builder.testing.ConnectedDevice > No tests found.[Nexus_5X_API_18(AVD) - 4.3.1] FAILED
No tests found. This usually means that your test classes are not in the form that your test runner expects (e.g. don't inherit from TestCase or lack @Test annotations).
ちなみに、AS上からテストファイルを開いて、テストクラスの左側に表示されてる単体実行のボタンを押すと、ちゃんと実行されて成功するんですよね...
そのときの build.gradle
android {
defaultConfig {
:
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
:
}
dependencies {
:
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
これで、少なくともAndroid8.1のエミューレータではしっかり動くことを確認しています。
原因
The issue is that the main dex list for the test APK does not contain the test classes. AndroidJUnitRunner when looking for the test classes, does not uses the patched class loader that contains all dex files, but it only examines classes.dex. Therefore, it does not find any test classes to run.
ここに書いてあることが全てなのですが、補足しておくと AndroidJUnitRunner
が classes.dex
しか見てくれない、つまり classesN.dex
などが無視されてしまうことが問題のようです。
mutlidexをtureにしているときは、こんな感じで複数のdexファイルができます。
肝心のテストクラスを探してみると、 classes2.dex
の中にあることがわかります。
AndroidJUnitRunner
は classes2.dex
は見ずに、 classes.dex
しか見てくれない。
よって No tests found.
ということらしいです。
解決策
先ほどと同じリンクにworkaroundも書かれています。
android.enableD8MainDexList=false
as this will make as keep all annotated classes in the main dex. Even though that is not the required for the legacy multidex to work, it will fix the issue for this particular case.
gradle.properties
に android.enableD8MainDexList=false
と記述することで解消するようです。
これを記述することで、アノテーション付きのクラスをmainのdexファイルに入れたままにできるそうです。
試して見たところ、 build.gradle
に下記も必要でした。
dependencies {
:
androidTestImplementation 'com.android.support:multidex-instrumentation:1.0.3'
}
ここまでやって、ようやくAndroid4.3でもテストを通すことができました。
確認
念のため、 keep all annotated classes in the main dex
これも確認しておきましょう。
なるほど、たしかに classes.dex
にてテストクラスを発見することができました。
まとめ
multidex時にandroidTestを動かしたいなら、こんな感じ。
android {
defaultConfig {
:
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
:
}
dependencies {
:
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'com.android.support:multidex-instrumentation:1.0.3'
}
:
android.enableD8MainDexList=false