monkeyrunner

La herramienta monkeyrunner proporciona una API para escribir programas que controlan un dispositivo o emulador de Android fuera del código de Android. Con monkeyrunner, puedes escribir un programa de Python que instale una aplicación de Android o un paquete de prueba, lo ejecute, envíe combinaciones de teclas, tome capturas de pantalla de la interfaz de usuario y almacene esas imágenes en la estación de trabajo. La herramienta monkeyrunner está diseñada principalmente para probar aplicaciones y dispositivos a nivel funcional o de marco de trabajo, y para ejecutar conjuntos de pruebas de unidades, aunque puedes usarla con otros fines.

La herramienta monkeyrunner no está relacionada con la IU/Application Exerciser Monkey, también conocida como herramienta monkey. La herramienta monkey se ejecuta directamente en el shell adb del dispositivo o emulador, y genera flujos pseudoaleatorios de los eventos del usuario y del sistema. En comparación, la herramienta monkeyrunner controla los dispositivos y emuladores desde una estación de trabajo mediante el envío de comandos y eventos específicos desde una API.

La herramienta monkeyrunner proporciona estas funciones únicas para pruebas de Android:

  • Control de varios dispositivos: La API de monkeyrunner puede aplicar uno o más conjuntos de pruebas en varios dispositivos o emuladores. Puedes conectar físicamente todos los dispositivos o iniciar todos los emuladores a la vez (o ambos), conectar cada uno de forma programática y luego ejecutar una o más pruebas. También puedes iniciar la configuración del emulador de forma programática, ejecutar una o más pruebas y luego apagar el emulador.
  • Pruebas funcionales: monkeyrunner puede ejecutar una prueba automatizada de inicio a fin de una aplicación de Android. Debes proporcionar los valores de entrada con combinaciones de teclas o eventos de entrada táctil, y visualizar los resultados como capturas de pantalla.
  • Pruebas de regresión: monkeyrunner puede probar la estabilidad de la aplicación ejecutándola y comparando las capturas de pantalla resultantes con un conjunto de capturas que se sabe que son correctas.
  • Automatización extensible: Dado que monkeyrunner es un kit de herramientas de API, puedes desarrollar un sistema completo de módulos y programas basados en Python para controlar dispositivos Android. Además de usar la API de monkeyrunner, puedes usar los módulos estándar os y subprocess de Python para llamar a las herramientas de Android, como Android Debug Bridge.

    También puedes agregar tus propias clases a la API de monkeyrunner. Esto se describe más detalladamente en la sección Cómo ampliar monkeyrunner con complementos.

La herramienta monkeyrunner usa Jython, una implementación de Python que usa el lenguaje de programación Java. Jython permite que la API de monkeyrunner interactúe fácilmente con el marco de trabajo de Android. Con Jython, puedes usar la sintaxis de Python para acceder a constantes, clases y métodos de la API.

Un programa monkeyrunner simple

Este es un programa monkeyrunner simple que se conecta a un dispositivo y crea un objeto MonkeyDevice. Mediante el objeto MonkeyDevice, el programa instala un paquete de aplicaciones de Android, ejecuta una de las actividades y envía los eventos de clave a la actividad. El programa luego toma una captura de pantalla del resultado y crea un objeto MonkeyImage. A partir de este objeto, se escribe un archivo .png que contiene la captura de pantalla.

    # 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')
    

La API de monkeyrunner

La API de monkeyrunner está contenida en tres módulos del paquete com.android.monkeyrunner:

  • MonkeyRunner: Es una clase de métodos de utilidad para programas de monkeyrunner. Esta clase proporciona un método para conectar monkeyrunner a un dispositivo o emulador. También proporciona métodos que permiten crear IU para un programa monkeyrunner y para mostrar la ayuda integrada.
  • MonkeyDevice: Representa un dispositivo o emulador. Esta clase proporciona métodos para instalar y desinstalar paquetes, iniciar una actividad y enviar eventos de entrada táctil o del teclado a una aplicación. También debes usar esta clase para ejecutar paquetes de prueba.
  • MonkeyImage: Representa una imagen de captura. Esta clase proporciona métodos para capturar pantallas, convertir imágenes de mapas de bits a varios formatos, comparar dos objetos de MonkeyImage y escribir una imagen en un archivo.

En un programa Python, accedes a cada clase como un módulo de Python. La herramienta monkeyrunner no importa estos módulos automáticamente. Para importar un módulo, usa la declaración from de Python:

    from com.android.monkeyrunner import <module>
    

donde <module> es el nombre de clase que quieres importar. Puedes importar más de un módulo en la misma declaración from; para ello, separa los nombres de módulos con comas.

Cómo ejecutar monkeyrunner

Puedes ejecutar programas de monkeyrunner desde un archivo o ingresar declaraciones de monkeyrunner en una sesión interactiva. En ambos casos, debes invocar el comando monkeyrunner, que se encuentra en el subdirectorio tools/ del directorio del SDK. Si proporcionas un nombre de archivo como argumento, el comando monkeyrunner ejecutará el contenido del archivo como un programa de Python. De lo contrario, iniciará una sesión interactiva.

La sintaxis del comando monkeyrunner es

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

En la tabla 1, se explican las marcas y los argumentos.

Tabla 1: Marcas y argumentos de monkeyrunner.

Argumento Descripción
-plugin <plugin_jar> Opcional: Especifica un archivo .jar que contenga un complemento para monkeyrunner. Si quieres obtener más información sobre los complementos de monkeyrunner, consulta Cómo ampliar monkeyrunner con complementos. Para especificar más de un archivo, incluye el argumento varias veces.
<program_filename> Si proporcionas este argumento, el comando monkeyrunner ejecutará el contenido del archivo como un programa de Python. Si no se proporciona el argumento, el comando iniciará una sesión interactiva.
<program_options> Opcional: Marcas y argumentos para el programa en <program_file>.

Ayuda integrada de monkeyrunner

Para generar una referencia de API para monkeyrunner, ejecuta lo siguiente:

    monkeyrunner help.py <format> <outfile>
    

Los argumentos son:

  • <format> es text para salida de texto sin formato, o html para salida HTML.
  • <outfile> es un nombre de ruta de acceso completo para el archivo de salida.

Cómo ampliar monkeyrunner con complementos

Puedes ampliar la API de monkeyrunner con clases escritas en el lenguaje de programación Java y compilarla en uno o más archivos .jar. Puedes usar esta función para ampliar la API de monkeyrunner con tus propias clases o para ampliar las clases existentes. También puedes usar esta función para inicializar el entorno de monkeyrunner.

A fin de proporcionar un complemento para monkeyrunner, invoca el comando monkeyrunner con el argumento -plugin <plugin_jar> que se describe en la Tabla 1.

En el código del complemento, puedes importar y ampliar las clases principales de monkeyrunner MonkeyDevice, MonkeyImage y MonkeyRunner en com.android.monkeyrunner (consulta La API de monkeyrunner).

Ten en cuenta que los complementos no te brindan acceso al SDK de Android. No puedes importar paquetes como com.android.app. Esto se debe a que monkeyrunner interactúa con el dispositivo o el emulador por debajo del nivel de las API del marco de trabajo.

La clase de inicio del complemento

El archivo .jar de un complemento puede especificar una clase cuya instancia se crea antes de que se inicie el procesamiento de la secuencia de comandos. Para especificar esta clase, agrega la clave MonkeyRunnerStartupRunner al manifiesto del archivo .jar. El valor debe ser el nombre de la clase que se ejecuta en el inicio. En el siguiente fragmento, se muestra cómo hacer esto dentro de una secuencia de comandos de compilación ant:

    <jar jarfile="myplugin" basedir="${build.dir}">
    <manifest>
    <attribute name="MonkeyRunnerStartupRunner" value="com.myapp.myplugin"/>
    </manifest>
    </jar>

    

Para obtener acceso al entorno de ejecución de monkeyrunner, la clase de inicio puede implementar com.google.common.base.Predicate<PythonInterpreter>. Por ejemplo, esta clase configura algunas variables en el espacio de nombres predeterminado:

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;
        }
    }