travis で Android (Kotlin 付き) のテストをするときにしたことのメモ
自分の作ってるアプリにテスト書いてtravisでやってくれるようにした話です。
テスト
長らくテスト全く書かずにしてきたのですがいい加減そろそろテスト書かないとなあと思ったのでテストをシュババっと書きました。*1
とりあえず gradle にシュッとそれっぽい依存を書いて
そして kotlin でパパっとテストを書きました。*2
kotlin でテストできるか不安でしたが java でちょっとだけ書いてそれを convert したものを参考に書いたら普通に動いてくれたので安心。
ということでとりあえずテストは完成。実機でも無事通りました。
travis の前準備(キーの暗号化)
今までは secret key とかは key.xml
的な秘蔵のxmlに保存していましたが、 travis でコンパイルできるようにする必要があるためなんとかして travis にキーを伝える必要があります。
ここで travis のキー暗号化機能を使います。
これを使えば暗号化されたキーを置くと、travis がいい感じに展開してくれて環境変数にキーなどを export
してくれます。
それを gradle
で読むようにして、キーを resource(@string)
経由ではなく BuildConfig
経由で直接埋め込んでしまうという作戦でこうなりました。
def FLICKR_KEY def TWITTER_KEY ... def file = project.file('key.properties') if (file.exists()) { def properties = new Properties() properties.load(file.newDataInputStream()) FLICKR_KEY = properties.get("FLICKR_KEY") TWITTER_KEY = properties.get("TWITTER_KEY") ... } else { FLICKR_KEY = System.getenv("FLICKR_KEY") TWITTER_KEY = System.getenv("TWITTER_KEY") ... } buildConfigField "String", "FLICKR_KEY", "\"${FLICKR_KEY}\"" buildConfigField "String", "TWITTER_KEY", "\"${TWITTER_KEY}\"" ...
ローカルでは key.properties
の値を読むようにし、 travis では環境変数を読むようにしました。
key.properties
の存在を確認し、存在すればプロパティとして読み込み〜〜という動作になっています。
ちなみに key.properties
は
FLICKR_KEY = xxxxxxxxxxxxxxx TWITTER_KEY = xxxxxxxxxxxx ~~~~
といった感じです。
そして travis 用の暗号化されたキーを生成します。
その前にレポジトリを travis に連携させる必要があるのでgithub経由でログインして連携させ、
$ sudo gem install travis
して、.travis.yml
を touch
しておけば、
$ travis encrypt <環境変数名>=<値> --add
すると勝手に .travis.yml
に追加してくれます。便利!
travis
次は .travis.yml
に Android 用の設定をゴリゴリ書きます。
Building an Android Project (beta) - Travis CI
が公式のガイド*3です。
実装は
等を参考にして書きました。
# .travis.yml language: android jdk: oraclejdk7 # なくてもいいかも? sudo: false # 多少早くなるらいしい env: global: - GRADLE_OPTS="-Xmx512m -XX:MaxPermSize=512m" - ADB_INSTALL_TIMEOUT=10 - secure: <SECRET-KEY1> - secure: <SECRET-KEY2> android: components: - android-23 - android-22 - build-tools-23.0.1 - build-tools-22.0.1 - extra-android-support - extra-android-m2repository - extra-google-m2repository - sys-img-armeabi-v7a-android-19 # Emulator Management: Create, Start and Wait before_script: - echo no | android create avd --force -n test -t android-19 --abi armeabi-v7a - emulator -avd test -no-skin -no-audio -no-window & - android-wait-for-emulator - adb shell input keyevent 82 & script: - ./gradlew --info clean lint :app:connectedAndroidTest
kotlin でしたが後述のヒープサイズ以外は特別な設定は必要としませんでした。さすが kotlin。
つまづきどころ
./gradlew: Permission denied
これは gradlew
のパーミッションが正しく設定されてないことによるエラーです。chmod +x gradlew
すると直りました。
> failed to find target with hash string 'android-22' in: /usr/local/android-sdk
これはプロジェクト内に直接 volley を submodule
で組み込んでおり、 volley は Android SDK 22 でビルドする必要があるために起きたエラーです。android-22
を components
に加えましょう。
> failed to find Build Tools revision 22.0.1
これも↑とほぼ同じエラーですね。 build-tools-22.0.1
を加えましょう。
* What went wrong: PermGen space
メモリが足りていないことが原因でした。 kotlin とか sbt とか使うとこのエラーがよく出るみたいです。
- GRADLE_OPTS="-Xmx512m -XX:MaxPermSize=512m"
を env
の global
に加えるとヒープが大きくなってビルドできました。この値は大きすぎると travis の制限に引っかかるようなので 512 か 1024 程度でいいと思います。
Unable to upload some APKs
ShellCommandUnresponsiveException
インストール時間の制限に引っかかった*4?と思って
- ADB_INSTALL_TIMEOUT=10
を env
の global
に入れたら直りました。*5
Timeout (360 seconds) reached; failed to start emulator
emulator がいつまでも starting
だったというエラー。エミュレータに andorid-23 を使うとそんなエラーになったのでまだ不安定なのかもしれません。いい感じにfixする方法も特に見つからず*6、仕方ないので android-22 にすると出なくなりました。
その他
先ほど貼った GitHub のレポジトリにある通り、
matrix: - ANDROID_TARGET=android-22 - ANDROID_TARGET=android-19 - ANDROID_TARGET=android-17 - ANDROID_TARGET=android-15
を env
に設定し、
- echo no | android create avd --force -n test -t $ANDROID_TARGET --abi armeabi-v7a
とすることで、複数の環境変数で並列テストしてくれます。もちろん、対応したバージョンの sys-img
を読み込む必要があります。
テストに通ったのが GitHub に反映された様子
参考になったサイト
Kotlin でテスト。
BuildConfig
について。
BuildConfig
について。
sbt の travis マニュアル
関連記事
*1:軽いテストでActivity関係の闇なテストは行っていません
*2:expected と actual の順番がミスって逆になっています http://qiita.com/deflis/items/645451d7fd85932d1134
*3:実は少し古くて、最新のバージョンのビルドツール使えるし、androidも使えます。ただ最新の andorid は後述の通りちょっと不安定
*4:http://stackoverflow.com/questions/28949722/android-tests-fail-on-travis-with-shellcommandunresponsiveexception
*5:ですが今見たらその時エラーが出てたビルドも後から見るとインストールに成功してて、よくわからないです… まあとりあえずオプションを付ければ直る?
*6:タイムアウト伸ばすだけなら wait_for_emulator コマンドを内部のを使わずに、タイムアウト時間を fix したものを curl するなりして持ってきてからそれを実行すればいい話ではあるのですが、他のエミュレータは6分もかからないので異常な気がする、けどそんなもんな気もする