monkeyrunner

旧版 monkeyrunner 工具提供了一个 API,用于编写可从 Android 代码外部控制 Android 设备或模拟器的程序。

monkeyrunner 工具主要用于在功能/框架级测试应用和设备以及运行单元测试套件,不过您也可以将其用于其他用途。使用 monkeyrunner,您可以编写 Python 程序来安装 Android 应用或测试软件包,运行该应用或软件包,向其发送模拟击键,截取其界面的屏幕截图,并将屏幕截图存储到工作站中。

注意:monkeyrunner API 未进行维护。我们建议您改用 UI Automator 测试框架。

monkeyrunner 工具与 UI/Application Exerciser Monkey(即 monkey 工具)无关。monkey 工具直接在设备或模拟器上的 adb shell 中运行,并生成伪随机用户和系统事件流。相比之下,monkeyrunner 工具通过从 API 发送特定命令和事件来从工作站控制设备和模拟器。

monkeyrunner 工具为 Android 测试提供了以下功能:

  • 多设备控制:monkeyrunner API 可以跨多个设备或模拟器应用一个或多个测试套件。您可以通过物理方式一次连接所有设备并/或启动所有模拟器,以编程方式依次连接到每个设备或模拟器,然后运行一个或多个测试。您也可通过编程方式启动模拟器配置,运行一个或多个测试,然后关闭模拟器。
  • 功能测试:monkeyrunner 可以对 Android 应用自始至终地运行自动化测试。您可以通过按键或触摸事件提供输入值,并以屏幕截图的形式查看结果。
  • 回归测试:monkeyrunner 可以通过运行应用并将其输出屏幕截图与一组已知正确的屏幕截图进行比较来测试应用稳定性。
  • 可扩展的自动化:由于 monkeyrunner 是一个 API 工具包,因此您可以开发一套系统,其中包括基于 Python 的模块和用于控制 Android 设备的程序。除了使用 monkeyrunner API 本身,您还可以使用标准 Python os 和 subprocess 模块来调用 Android 工具,例如 Android 调试桥。

    您还可以向 monkeyrunner API 添加自己的类。使用插件扩展 monkeyrunner 部分对此进行了更详细的说明。

monkeyrunner 工具使用 Jython,这是一种使用 Java 编程语言的 Python 实现。Jython 让 monkeyrunner API 与 Android 框架可以轻松交互。借助 Jython,您可以使用 Python 语法访问 API 的常量、类和方法。

一个简单的 monkeyrunner 程序

下面介绍了一个简单的 monkeyrunner 程序,该程序会连接到一台设备,并创建一个 MonkeyDevice 对象。该程序使用 MonkeyDevice 对象安装 Android 应用软件包,运行其中一个 Activity,并向该 Activity 发送按键事件。然后,该程序会截取结果的屏幕截图,并创建一个 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
# whether 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 软件包的三个模块中:

  • MonkeyRunner:一个包含用于 monkeyrunner 程序的实用程序方法的类。此类提供了用于将 monkeyrunner 连接到设备或模拟器的方法。它还提供了用于为 monkeyrunner 程序创建界面以及显示内置帮助的方法。
  • MonkeyDevice:代表设备或模拟器。此类提供了用于安装和卸载软件包、启动 Activity 以及向应用发送键盘或轻触事件的方法。此外,您还可以使用此类运行测试软件包。
  • MonkeyImage:代表屏幕截图。此类提供了用于截屏、将位图转换为各种格式、比较两个 MonkeyImage 对象以及将图片写入文件的方法。

在 Python 程序中,您可以将每个类作为 Python 模块来使用。monkeyrunner 工具不会自动导入这些模块。要导入模块,请使用 Python from 语句:

from com.android.monkeyrunner import <module>

其中 <module> 是要导入的类名称。您可以在同一个 from 语句中导入多个模块,只需用英文逗号分隔各模块名称即可。

运行 monkeyrunner

您可以通过文件运行 monkeyrunner 程序,也可以在交互式会话中输入 monkeyrunner 语句。您可以通过调用 monkeyrunner 命令(位于 SDK 目录的 tools/ 子目录中)来执行这两项操作。如果您以参数的形式提供文件名,monkeyrunner 命令会将文件的内容作为 Python 程序运行;否则,它会启动一个交互式会话。

以下是 monkeyrunner 命令的语法:

monkeyrunner -plugin <plugin_jar> <program_filename> <program_options>

表 1 对其中的 monkeyrunner 标志和参数进行了说明。

表 1. monkeyrunner 标志和参数

参数 说明
-plugin <plugin_jar> (可选)指定包含 monkeyryrunner 插件的 monkeyrunner 文件。如需详细了解 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,并将其构建为一个或多个 JAR 文件。您可以借助此功能使用自己的类扩展 monkeyrunner API,或扩展现有的类。您还可以使用此功能初始化 monkeyrunner 环境。

如需为 monkeyrunner 提供插件,请在调用 monkeyrunner 命令时使用表 1 中所述的 -plugin <plugin_jar> 参数。

在插件代码中,您可以导入和扩展 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;
    }
}