AndroidのE2Eテストの自動化を安定させるためにやったこと

kasama
『JapanTaxi』アプリのE2Eテストの自動化を行なっている笠間です。
JapanTaxi AdventCalendarの12日目を担当することになりました。

今年はAndroid・iOSのE2Eテスト自動化を中心に進めてきました。進める中でいろいろ思考錯誤してきたTIPSをひとつ紹介したいと思います。

Emulator不安定問題

『JapanTaxi』アプリのE2Eテストでは、一部実機を使っていますが、ほとんどはEmulatorを使っています。最初は同じEmulatorを使って繰り返し自動テストを行なっていました。しかし、ある日失敗している結果を実機で再確認していたところ、Emulatorの結果と実機の結果で異なるものがあることが判明しました。調べてみると、Emulatorに本来テストすべきapkが入っておらず、前回リリースされたapkでテストをしていることが判明しました。おそらくapkのインストールがうまくできておらず、しかもエラーになっていなかったため気づけない状態だったようです。

やったこと

この問題を解決するために新しくEmulatorを作ってからテストを実行するようにしました。同じEmulatorを毎回使うと問題になりやすいのであれば、Emulatorを作って起動するというRakeタスクを作ることでいつもきれいな環境でテストできます。

ソースコードは以下のようになります。コマンドを叩いているだけなのでエラー時の処理は別途入れる必要があります。


task :start do
    # ライセンスに同意する
    `yes | sdkmanager --licenses`
    # 欲しいイメージをダウンロードする。今回はAndroid10(API Version29)にします
    `sdkmanager "system-images;android-29;google_apis_playstore;x86"`
    # 取ってきたイメージを使ってEmulatorを作成する
    `avdmanager create avd -n ENV['EMULATOR_NAME'] -k "system-images;android-29;google_apis_playstore;x86" -c 100M --device 'pixel'`
     # 作ったEmulatorを起動させる。Androidのテスト実行は並列で行なっていることからport指定しています。またデフォルトだとカメラなしのEmulatorになってしまうのでカメラの設定も行います。
    `emulator ENV['EMULATOR_NAME'] -port 6001 -skin "1080x1920" -memory 2048 -camera-back emulated -camera-front emulated >/dev/null 2>&1 &`

    raise "Can not start Android emulator. Name: ENV['EMULATOR_NAME'] Port: 6001 unless android_started?
    # API Versionによってはアプリを起動するとGoogle Playアプリを更新してと出てしまうため入れています。
    `adb -s ENV['UDID'] install -r env/android/*.apk`
end

またEmulatorを起動したあと、Emulatorが起動完了したかどうかも確認する必要があります。よって完了したかどうかのチェックメソッドも設けました。


def android_started?
  3.times do
    boot_completed = `adb -s ENV['UDID'] shell getprop sys.boot_completed`.chomp
    # 起動していないときはemptyになる
    if boot_completed.empty?
      sleep 10
      next
    end
    return true if boot_completed == "1"
  end
  false
end

Emulatorを作ってテストをして…を繰り返すとたくさんのEmulatorが作られてしまうのでEmulatorをStopして削除するRakeタスクも作りました。


task :stop do
    if ENV['EMULATOR_NAME']
      processes = `pgrep -f ENV['EMULATOR_NAME']`
      unless processes.empty?
        processes.split("\n").each do |process|
          Process.kill(:KILL, process.to_i)
        end
      end
      `avdmanager delete avd -n ENV['EMULATOR_NAME']`
    else
    end
end

これらのタスクを実行してからは、Androidのテスト実行がだいぶ安定してきました。今後も安定したテストを作り続けプロダクトの品質向上に貢献していきます。

JapanTaxiに興味を持ったら、まずはお話しませんか?