Mutlidexを使ってる時にAndroidTestが動かない問題とその対処方法

お久しぶりです。くぎみやです。


問題発覚

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


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のエミューレータではしっかり動くことを確認しています。


原因

https://issuetracker.google.com/u/1/issues/78108767


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.


ここに書いてあることが全てなのですが、補足しておくと AndroidJUnitRunnerclasses.dex しか見てくれない、つまり classesN.dex などが無視されてしまうことが問題のようです。

mutlidexをtureにしているときは、こんな感じで複数のdexファイルができます。

スクリーンショット 2018-04-27 12.33.28.png

肝心のテストクラスを探してみると、 classes2.dex の中にあることがわかります。

スクリーンショット 2018-04-27 12.39.41.png

AndroidJUnitRunnerclasses2.dex は見ずに、 classes.dex しか見てくれない。

よって No tests found. ということらしいです。


解決策

https://issuetracker.google.com/u/1/issues/78108767

先ほどと同じリンクに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.propertiesandroid.enableD8MainDexList=false と記述することで解消するようです。

これを記述することで、アノテーション付きのクラスをmainのdexファイルに入れたままにできるそうです。

試して見たところ、 build.gradle に下記も必要でした。


build.gradle

dependencies {

:
androidTestImplementation 'com.android.support:multidex-instrumentation:1.0.3'
}

ここまでやって、ようやくAndroid4.3でもテストを通すことができました。


確認

念のため、 keep all annotated classes in the main dex これも確認しておきましょう。

スクリーンショット 2018-04-27 12.49.03.png

なるほど、たしかに classes.dex にてテストクラスを発見することができました。


まとめ

multidex時にandroidTestを動かしたいなら、こんな感じ。


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'
androidTestImplementation 'com.android.support:multidex-instrumentation:1.0.3'
}



gradle.properties

:

android.enableD8MainDexList=false