バグの手元での再現を自動化したい
最近バグ系のissue潰しが多く,こんなことをたくさんしてます.
- バグを手元の端末で再現
- コードの修正
- バグが消えたか端末上で確認
- 様々な条件(異なるOS等)で,バグが消えたか確認
- PullRequestを出す
特に,バグの再現手順に
文字入力(ログイン処理等)なんかがあると何度もやるのつらいです..
そこで,MonkeyRecorderとMonkeyRunnerを使って,
繰り返し行う端末操作をスクリプト化してみました.
今回は,その方法について書きます.
話の流れは以下のようになります.
- MonkeyRecorderを使った端末操作の記録
- MonkeyRunnerによる端末操作の再現
MonkeyRecorderを使った端末操作の記録
端末の用意
まず,バグを再現する端末を用意します.
実機で行うなら,実機をPCにUSBでつなげばOKです.
エミュレータなら,エミュレータを起動してください.(以下,エミュレータ起動参考コード)
ls ~/.android/avd
# Nexus_5_API_22_x86.avd Nexus_5_API_22_x86.ini metrics
<path_to_android-sdks>/tools/emulator -avd Nexus_5_API_22_x86
対象アプリも起動しておきましょう.(手動で起動してもokです)
# adb shell am start -n <package名>/<対象Activityクラス名>
$ adb shell am start -n com.ikota.flickrclient/.ui.PopularListActivity
MonkeyRecorderで操作を記録
MonkeyRecorderの起動はスクリプトから行います.
以下スクリプト(run_monkeyrecorder.py
)を手元に用意してください.
from com.android.monkeyrunner import MonkeyRunner
from com.android.monkeyrunner.recorder import MonkeyRecorder
device = MonkeyRunner.waitForConnection()
MonkeyRecorder.start(device)
run_monkeyrecorder.py
はこちらのgistにも置いてあります.
(以下 ~/Desktop/run_monkeyrecorder.py
にこのファイルがあるとして進めます)
それでは,MonkeyRecorderを起動しましょう.
$ <android-sdk path>/tools/monkeyrunner ~/Desktop/run_monkeyrecorder.py
起動すると,以下画面右側にあるようなwindowが表示されるはずです.(これがMonkeyRecorderです)
MonkeyRecorder上には,以下2つの画面が表示されています.
- 記録対象端末のスクリーンキャプチャ (左側)
- 行われた端末操作のログ (右側)
では,MonkeyRecorder上で記録したい操作を行いましょう.
MonkeyRecorder上での主な操作は以下になります.
- タップ : MonkeyRecorder上のスクリーンキャプチャの任意の場所をクリック
- 文字入力 : MonkeyRecorder上の
TypeSomething
を押して,入力したい文字を入力 - スワイプ : MonkeyRecorder上の
Fling
を押して,スワイプ方向の情報を入力
MonkeyRecorder上の操作は,端末上で実行され,
以下画像のように右側の領域に操作ログが追加されていきます.
記録したい操作が終わったら,MonkeyRecorder上のExport Actions
をクリックして,
ログファイルを任意の場所に作成してください.
(以下,~/Desktop/bug_reproduce.txt
に作成したとして進めます)
MonkeyRunnerによる端末操作の再現
その前に...
MonkeyRecorderで作成したログファイルは,そのままではMonkeyRunnerに渡せません.
以下のような,スクリプトへの変換が必要になります.
今回,この変換操作を行うスクリプトmonkey_converter.py
を作成したので,
これを使って再現スクリプトへ変換します.
変換スクリプトは,こちらのgistに置いてあります.
(以下,変換スクリプトは,~/Desktop/monkey_converter.py
にあるものとします)
使い方は以下のようになります.
cd ~/Desktop
# python monkey_converter.py <log file> <script_name>
$ python monkey_converter.py bug_reproduce.txt bug_reproduce.py
これで,~/Desktop/bug_reproduce.py
という名前で再現スクリプトができました.
再現スクリプトの実行
あとは,以下コマンドで再現スクリプトを実行すれば,記録した動作が端末上で実行されます.
$ <path to android-sdks>/tools/monkeyrunner bug_reproduce.py
コードを修正したら上のコマンドを実行するだけで,
修正が上手くいったか確認できるので便利です.
最後に
この再現スクリプトは,端末の座標系に依存しているので,
作成した端末と異なる端末で実行すると期待した通りに動かないので注意してください.
ただし,「実機のNexus5で再現スクリプトを作成して,Nexus5のエミュレータで再現スクリプトを実行」は可能です.
開発アプリのログイン/ログアウト処理をスクリプト化しておくと,
Emailアドレス+パスワードの入力+ログイン処理が自動化できて,
個人的に便利だなと感じています.
追記
「MonkeyRecorderのログファイル」から「再現スクリプト」への変換を行う
monkey_converter.py
で行っていることについて以下に簡単に書きました.
変換スクリプトでやっていること
変換スクリプトでは,以下のような変換を行っています.
TOUCH|{'x':864,'y':152,'type':'downAndUp',}
↓
device.touch(864, 152, MonkeyDevice.DOWN_AND_UP)
print 'Executing : device.touch(864, 152, MonkeyDevice.DOWN_AND_UP)'
MonkeyRunner.sleep(5.0)
本来なら上の1行だけで十分ですが,
2行目のログを吐くコードと,
3行目のACTION_INTERVAL_IN_SECONDS
にセットされた秒数(デフォルトは5秒)待つコード
が追加してあります.
3行目のコードがないと,MonkeyRunnerから送った命令が端末で実行されている最中に
次の命令が送られてしまい,期待した動作にならない場合があります.
特にエミュレータで再現する場合は,この秒数を5秒など大きめにとっておくのがオススメです.
端末で行われる操作のタイミングが合わない場合は,
作成されたスクリプトの'MonkeyRunner.sleep(5.0)'の部分を調整してみてください.