つい先日MultiDexが必要になってしまうことがありまして、その際にrobospockでテストが動かなくなりました
とりあえず強引に対応してみた備忘録です
結論だけ書くと、「それ用にbuild typeを追加した」になります
robospockに関して
spockっていうテストフレームワーク+ Robolectric ですね
そんな本家サイト見ると…
-
robospock plugin 使うんやで
- 2015/01/07現在での最新コミットへのリンクにしています
- versionは0.4.4やで!
とかになっていますが、現状robospockは結構前から0.5.0になっていますし、0.5.0使おうとするとそのpluginじゃ駄目だし…
余談ですが前にAndroidAnnotations + lombok と spock + Robolectric みたいな環境作ってみたなの書いています
がよく考えたら、今AndroidAnnotationもGuavaも使ってないし使いたくない
robospock 0.5.0 でも gradle plugin使いたい
Android StudioでRoboSpockを使えるようにする の記事でもその有志のplugin使っていますね
robospock本家sampleを参考にして、そもそもplugin使わない
本家のsampleアプリを見ると、何気にplugin使ってません
コンパイル結果のclassを集めてjarにして、それに対してテストするという手法を取っています
自分はその方法を真似てrobospockを使っています
本題
とりあえずrobospockを使ってテストを書く
とりあえずContextを利用した適当なテストを追加したProjectがこちらです
Activityに対してテスト書きたいところですけど、AcitionBarActivityにはまだ対応していないので上記のような適当な奴になっています
そんなこともあるんで、個人的にはrobospockは「Contextに依存するコードもUnitTestできる!」ぐらいの位置づけで使っています
multidexを有効化する
こんな感じでいっぱいlibraryを詰め込むとあっという間に65535を超えますね
- support系やgmsは必須だし〜
- ViewInject系のライブラリは欲しいし〜
- ネットワークに繋げるのに楽なライブラリは欲しいし〜
- そうするとJsonのパースとか楽したいし〜
みたいな感じでガンガン入れてみたんですけどなかなか超えなかった…
multidexを有効化しないとこんなエラーが出ます
com.android.ide.common.internal.LoggedErrorException: Failed to run command:
/usr/local/opt/android-sdk/build-tools/21.1.2/dx -JXmx4g --dex --no-optimize --output /private/tmp/android/MyApplication/app/build/intermediates/dex/debug --input-list=/private/tmp/android/MyApplication/app/build/intermediates/tmp/dex/debug/inputList.txt
Error Code:
2
Output:
UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:502)
at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:277)
at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:491)
at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:168)
at com.android.dx.merge.DexMerger.merge(DexMerger.java:189)
at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:454)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:303)
at com.android.dx.command.dexer.Main.run(Main.java:246)
at com.android.dx.command.dexer.Main.main(Main.java:215)
at com.android.dx.command.Main.main(Main.java:106)
ちなみにこの状態でメソッド数は
- 65344
でした
この段階で ./gradlew clean test:test
とかやっても動きます
4系でも動くApkを作るように…
この段階で ./gradlew clean test:test
とかやると…
com.example.myapplication.SampleSpec > classMethod FAILED
java.lang.RuntimeException: java.lang.RuntimeException: Multi dex installation failed. SDK 1 is unsupported. Min SDK version is 4.
Caused by:
java.lang.RuntimeException: Multi dex installation failed. SDK 1 is unsupported. Min SDK version is 4.
とか出てきて大変残念な感じになります
他にも
error: package android.support.multidex does not exist
import android.support.multidex.MultiDexApplication;
とか
本家のIssueにも上がっているパターンとかも遭遇できて色々と辛いです
とりあえずテストが動くようにする
前段の差分から、Manifestというか単にApplicationがMultiDexApplication使わなければ良いだけです
冒頭で書いた通り、build type を追加しただけです
MultiDex避ければ基本問題ない
-
65K避けよう… とDocumentにはあります
- その為?なのかplay-servicesが細分化されていました(6.5.87から)
- play-servicesが必要なものだけ入れられれば確かに助かる
- extras/google/m2repository/com/google/android/gms/ 以下をみると次のような感じに
play-services
play-services-ads
play-services-all-wear
play-services-appindexing
play-services-appstate
play-services-base
play-services-cast
play-services-drive
play-services-fitness
play-services-games
play-services-identity
play-services-location
play-services-maps
play-services-panorama
play-services-plus
play-services-wallet
play-services-wearable
他にも上記Documentでも「Proguard」に関して触れていますが、
個人的にDebug/UnitTest如きで使いたくないってのがあります
最大の理由は Buildに時間がかかってイライラするから
ということで、もしMultiDex使わなければならない状況になって、且つrobospock使ってて動かなくなった!!
みたいなニッチな場合にご参考までにどうぞ
and もっと良い解決方法ください
and robolectric & robospock のversion up待ってる