monkeyrunner ツールは、Android コードの外部から Android デバイスまたはエミュレータを制御するプログラムを作成するための API を提供します。monkeyrunner を使用すると、Android アプリまたはテスト パッケージのインストールと実行、キー操作の送信、ユーザー インターフェースのスクリーンショットの取得、スクリーンショットのワークステーションへの保存を行う Python プログラムを作成できます。monkeyrunner ツールは機能 / フレームワーク レベルでアプリとデバイスをテストすることと、単体テストスイートを実行することを主な目的として設計されていますが、それ以外の目的でも自由に使用できます。
monkeyrunner ツールは、UI/Application Exerciser Monkey(別名 monkey
ツール)とは無関係です。monkey
ツールは、デバイスまたはエミュレータ上の adb
シェル内で直接実行され、ユーザー イベントとシステム イベントの擬似ランダム ストリームを生成します。これに対して、monkeyrunner ツールは API から特定のコマンドとイベントを送信して、ワークステーションからデバイスとエミュレータを制御します。
monkeyrunner ツールは、Android のテストを行うための以下のような独自の機能を備えています。
- 複数のデバイスの制御: monkeyrunner API は、複数のデバイスまたはエミュレータに 1 つ以上のテストスイートを適用できます。すべてのデバイスを物理的に接続するか、すべてのエミュレータを起動するか、またはその両方を行い、プログラムで順番に接続して、1 つ以上のテストを実行できます。また、エミュレータ構成をプラグラムで起動し、1 つ以上のテストを実行してからエミュレータをシャットダウンすることもできます。
- 機能テスト: monkeyrunner は、Android アプリの起動から終了までを自動化してテストできます。キー操作またはタッチイベントの入力値を渡すと、結果がスクリーンショットとして表示されます。
- 回帰テスト: monkeyrunner では、アプリを実行し、出力されたスクリーンショットと正常であるとわかっているスクリーンショットを比較することで、アプリの安定性をテストできます。
-
拡張可能な自動化: monkeyrunner は API ツールキットであるため、Python ベースのモジュールとプログラムのシステム全体を開発して、Android デバイスを制御できます。monkeyrunner API 自体を使用する代わりに、Python の標準の
os
モジュールとsubprocess
モジュールを使用して、Android Debug Bridge などの Android ツールを呼び出すこともできます。また、monkeyrunner API に独自のクラスを追加することもできます。詳細については、プラグインを使用して monkeyrunner を拡張するセクションをご覧ください。
monkeyrunner ツールは、Java プログラミング言語を使用した Python の実装である Jython を使用しています。そのため、monkeyrunner API は Android フレームワークと簡単にやり取りできます。Jython では、Python 構文を使用して、API の定数、クラス、メソッドにアクセスできます。
シンプルな monkeyrunner プログラム
デバイスに接続して MonkeyDevice
オブジェクトを作成する簡単な monkeyrunner プログラムを以下に示します。このプログラムは、MonkeyDevice
オブジェクトを使用して Android アプリ パッケージをインストールし、そのアクティビティの 1 つを実行してキーイベントをアクティビティに送信します。次に、結果のスクリーンショットを取得して、MonkeyImage
オブジェクトを作成します。そして、このオブジェクトから、スクリーンショットを含む .png
ファイルを出力します。
# Imports the monkeyrunner modules used by this program from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice # Connects to the current device, returning a MonkeyDevice object device = MonkeyRunner.waitForConnection() # Installs the Android package. Notice that this method returns a boolean, so you can test # to see if the installation worked. device.installPackage('myproject/bin/MyApplication.apk') # sets a variable with the package's internal name package = 'com.example.android.myapplication' # sets a variable with the name of an Activity in the package activity = 'com.example.android.myapplication.MainActivity' # sets the name of the component to start runComponent = package + '/' + activity # Runs the component device.startActivity(component=runComponent) # Presses the Menu button device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP) # Takes a screenshot result = device.takeSnapshot() # Writes the screenshot to a file result.writeToFile('myproject/shot1.png','png')
monkeyrunner API
monkeyrunner API は、com.android.monkeyrunner
パッケージの 3 つのモジュールに含まれています。
-
MonkeyRunner
: monkeyrunner プログラム用のユーティリティ メソッドのクラス。このクラスは、monkeyrunner をデバイスまたはエミュレータに接続するためのメソッドを提供します。また、monkeyrunner プログラム用の UI を作成するメソッドと、組み込みヘルプを表示するメソッドも提供します。 -
MonkeyDevice
: デバイスまたはエミュレータを表します。このクラスは、パッケージのインストールとアンインストールを行うメソッド、アクティビティを開始するメソッド、キーボード イベントまたはタッチイベントをアプリに送信するメソッドを提供します。また、このクラスを使用してテスト パッケージを実行することもできます。 -
MonkeyImage
: スクリーン キャプチャの画像を表します。このクラスは、スクリーンをキャプチャするメソッド、ビットマップ画像をさまざまな形式に変換するメソッド、2 つの MonkeyImage オブジェクトを比較するメソッド、画像をファイルに書き出すメソッドを提供します。
Python プログラムでは、各クラスに Python モジュールとしてアクセスします。monkeyrunner ツールは、こうしたモジュールの自動インポートは行いません。モジュールをインポートするには、Python の from
ステートメントを使用します。
from com.android.monkeyrunner import <module>
ここで、<module>
はインポートするクラス名です。モジュール名をカンマで区切ると、1 つの from
ステートメントで複数のモジュールをインポートできます。
monkeyrunner を実行する
monkeyrunner プログラムを実行するには、ファイルから実行するか、対話型セッションで monkeyrunner ステートメントを入力します。どちらの方法を使用する場合も、SDK ディレクトリの tools/
サブディレクトリにある monkeyrunner
コマンドを呼び出します。引数としてファイル名を指定した場合、monkeyrunner
コマンドはファイルの内容を Python プログラムとして実行します。それ以外の場合は、対話型セッションを開始します。
monkeyrunner
コマンドの構文は以下のとおりです。
monkeyrunner -plugin <plugin_jar> <program_filename> <program_options>
フラグと引数については、表 1 を参照してください。
表 1. monkeyrunner
フラグと引数。
引数 | 説明 |
---|---|
-plugin <plugin_jar>
|
(任意)monkeyrunner のプラグインを含む .jar ファイルを指定します。
monkeyrunner のプラグインの詳細については、プラグインを使用して monkeyrunner を拡張するをご覧ください。複数のファイルを指定する場合は、引数を複数回指定します。
|
<program_filename>
|
この引数を指定した場合、monkeyrunner コマンドはファイルの内容を Python プログラムとして実行します。この引数を指定しなかった場合、コマンドは対話型セッションを開始します。
|
<program_options>
|
(任意)<program_file> 内のプログラムのフラグと引数。 |
monkeyrunner の組み込みヘルプ
以下を実行すると、monkeyrunner の API リファレンスを生成できます。
monkeyrunner help.py <format> <outfile>
引数は以下のとおりです。
-
<format>
は、書式なしテキストを出力する場合はtext
、HTML を出力する場合はhtml
です。 -
<outfile>
は、出力ファイルのパス付きの名前です。
プラグインを使用して monkeyrunner を拡張する
Java プログラミング言語で記述したクラスで monkeyrunner API を拡張し、1 つ以上の .jar
ファイルに組み込むことができます。この機能を使用して、独自のクラスによる monkeyrunner API の拡張または既存のクラスの拡張を行うことができます。monkeyrunner 環境を初期化することもできます。
monkeyrunner にプラグインを組み込むには、表 1 で説明した -plugin <plugin_jar>
引数を指定して monkeyrunner
コマンドを呼び出します。
プラグインのコードで、com.android.monkeyrunner
内にある monkeyrunner のメインクラス MonkeyDevice
、MonkeyImage
、および MonkeyRunner
をインポートまたは拡張できます(monkeyrunner API を参照)。
なお、プラグインは Android SDK にアクセスできず、com.android.app
などのパッケージをインポートできません。これは、monkeyrunner がフレームワーク API 以下のレベルでデバイスまたはエミュレータとやり取りするためです。
プラグイン起動クラス
プラグインの .jar
ファイルでは、スクリプト処理の開始前にインスタンス化されるクラスを指定できます。このクラスを指定するには、MonkeyRunnerStartupRunner
キーを .jar
ファイルのマニフェストに追加します。値は、起動時に実行されるクラスの名前であることが必要です。次のスニペットは、ant
ビルド スクリプト内でこれを行う方法を示しています。
<jar jarfile="myplugin" basedir="${build.dir}"> <manifest> <attribute name="MonkeyRunnerStartupRunner" value="com.myapp.myplugin"/> </manifest> </jar>
monkeyrunner のランタイム環境にアクセスするには、起動クラスで com.google.common.base.Predicate<PythonInterpreter>
を実装します。たとえば、次のクラスでは、デフォルトの名前空間にいくつかの変数を設定しています。
Kotlin
package com.android.example import com.google.common.base.Predicate import org.python.util.PythonInterpreter class Main: Predicate<PythonInterpreter> { override fun apply(anInterpreter: PythonInterpreter): Boolean { /* * Examples of creating and initializing variables in the monkeyrunner environment's * namespace. During execution, the monkeyrunner program can refer to the variables * "newtest" and "use_emulator" * */ anInterpreter.set("newtest", "enabled") anInterpreter.set("use_emulator", 1) return true } }
Java
package com.android.example; import com.google.common.base.Predicate; import org.python.util.PythonInterpreter; public class Main implements Predicate<PythonInterpreter> { @Override public boolean apply(PythonInterpreter anInterpreter) { /* * Examples of creating and initializing variables in the monkeyrunner environment's * namespace. During execution, the monkeyrunner program can refer to the variables "newtest" * and "use_emulator" * */ anInterpreter.set("newtest", "enabled"); anInterpreter.set("use_emulator", 1); return true; } }