monkeyrunner

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

monkeyrunner 工具主要用于在功能/框架级别测试应用程序和设备,以及运行单元测试套件,但您也可以将其用于其他目的。使用 monkeyrunner,您可以编写一个 Python 程序,它可以安装 Android 应用程序或测试包,运行它,向它发送按键,截取其用户界面的屏幕截图,并将屏幕截图存储在工作站上。

注意:monkeyrunner API 未维护。我们建议改用 应用程序爬虫 工具或 UI Automator 测试框架。

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

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

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

    您还可以向 monkeyrunner API 添加您自己的类。这在 使用插件扩展 monkeyrunner 部分中详细介绍。

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

一个简单的 monkeyrunner 程序

这是一个简单的 monkeyrunner 程序,它连接到设备,创建一个 MonkeyDevice 对象。使用 MonkeyDevice 对象,该程序安装 Android 应用程序包,运行其活动之一,并向该活动发送键盘事件。然后,该程序截取结果的屏幕截图,创建一个 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 程序创建 UI 和显示内置帮助的方法。
  • MonkeyDevice:表示设备或模拟器。此类提供用于安装和卸载包、启动活动以及向应用程序发送键盘或触摸事件的方法。您还可以使用此类运行测试包。
  • 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> (可选) 指定一个包含 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,并将这些类构建到一个或多个 JAR 文件中。 您可以使用此功能来扩展 monkeyrunner API,以包含您自己的类,或扩展现有类。 您还可以使用此功能初始化 monkeyrunner 环境。

若要向 monkeyrunner 提供插件,请使用 表 1 中所述的 -plugin <plugin_jar> 参数调用 monkeyrunner 命令。

在您的插件代码中,您可以导入和扩展 com.android.monkeyrunner 中的主要 monkeyrunnerMonkeyDeviceMonkeyImageMonkeyRunner(请参阅有关 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;
    }
}