monkeyrunner

A ferramenta legada monkeyrunner oferece uma API para criar programas que controlam um dispositivo ou emulador Android de fora do código Android.

A ferramenta monkeyrunner foi criada principalmente para testar apps e dispositivos no nível funcional/framework e para executar pacotes de testes de unidade, mas você pode usá-la para outras finalidades. Com o monkeyrunner, é possível criar um programa em Python que instala um app Android ou pacote de teste, executa, envia pressionamentos de tecla, faz capturas de tela da interface do usuário e armazena essas capturas na estação de trabalho.

Cuidado: a API monkeyrunner foi descontinuada. Recomendamos o uso da ferramenta App Crawler ou do framework de teste UI Automator.

A ferramenta monkeyrunner não está relacionada ao UI/Application Exerciser Monkey, também conhecido como ferramenta monkey. A ferramenta monkey é executada em um shell do adb diretamente no dispositivo ou emulador e gera fluxos pseudoaleatórios de eventos do usuário e do sistema. Por outro lado, a ferramenta monkeyrunner controla dispositivos e emuladores a partir de uma estação de trabalho, enviando comandos e eventos específicos de uma API.

A ferramenta monkeyrunner oferece estes recursos para testes do Android:

  • Controle de diversos dispositivos: a API monkeyrunner pode aplicar um ou mais pacotes de testes em vários dispositivos ou emuladores. É possível conectar fisicamente todos os dispositivos ou iniciar todos os emuladores (ou ambos) simultaneamente, conectar-se a um por vez programaticamente e, em seguida, executar um ou mais testes. Também é possível iniciar uma configuração do emulador de maneira programática, executar um ou mais testes e, em seguida, encerrar o emulador.
  • Teste funcional: o monkeyrunner pode executar um teste automatizado completo do início ao fim de um app Android. Informe valores de entrada com pressionamentos de tecla ou eventos de toque e confira os resultados como capturas de tela.
  • Teste de regressão: o monkeyrunner pode testar a estabilidade do app executando um app e comparando as capturas de tela de saída com um conjunto de capturas de tela sabidamente corretas.
  • Automação extensível: como monkeyrunner é um kit de ferramentas de API, é possível desenvolver um sistema de módulos e programas baseados em Python para controlar dispositivos Android. Além de usar a própria API monkeyrunner, você pode usar os módulos padrão os e subprocess Python para chamar ferramentas do Android, como a Android Debug Bridge.

    Também é possível adicionar suas próprias classes à API monkeyrunner. Isso é descrito com mais detalhes na seção Estender o monkeyrunner com plug-ins.

A ferramenta monkeyrunner usa o Jython, uma implementação do Python, que usa a linguagem de programação Java. O Jython permite que a API monkeyrunner interaja com facilidade com o framework do Android. Com o Jython, você pode usar a sintaxe do Python para acessar as constantes, classes e métodos da API.

Um programa simples do monkeyrunner

Veja a seguir um programa simples do monkeyrunner que se conecta a um dispositivo, criando um objeto MonkeyDevice. Usando o objeto MonkeyDevice, o programa instala um pacote de aplicativos para Android, executa uma das atividades relacionadas e envia eventos de teclas para a atividade. Em seguida, o programa faz uma captura de tela do resultado, criando um objeto MonkeyImage. A partir desse objeto, o programa grava um arquivo PNG que contém a captura de tela.

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

A API monkeyrunner

A API monkeyrunner é encontrada em três módulos no pacote com.android.monkeyrunner:

  • MonkeyRunner: uma classe de métodos utilitários para programas monkeyrunner. Essa classe oferece um método para conectar o monkeyrunner a um dispositivo ou emulador. Ela também disponibiliza métodos para criar IUs para um programa monkeyrunner e para mostrar a ajuda integrada.
  • MonkeyDevice: representa um dispositivo ou emulador. Essa classe oferece métodos para instalar e desinstalar pacotes, iniciar uma atividade e enviar eventos de teclado ou toque para um app. Essa classe também é usada para executar pacotes de teste.
  • MonkeyImage: representa uma imagem de captura de tela. Essa classe oferece métodos para fazer capturas de tela, converter imagens bitmap em vários formatos, comparar dois objetos MonkeyImage e gravar uma imagem em um arquivo.

Em um programa Python, você acessa cada classe como módulo Python. A ferramenta monkeyrunner não importa esses módulos automaticamente. Para importar um módulo, use a instrução Python from:

from com.android.monkeyrunner import <module>

Nela, <module> é o nome da classe que você quer importar. É possível importar mais de um módulo na mesma declaração from, separando os nomes dos módulos por vírgulas.

Executar o monkeyrunner

Você pode executar programas monkeyrunner em um arquivo ou inserindo instruções monkeyrunner em uma sessão interativa. Faça os dois invocando o comando monkeyrunner localizado no subdiretório tools/ do diretório do SDK. Se você informar um nome de arquivo como argumento, o comando monkeyrunner vai executar o conteúdo do arquivo como um programa Python. Caso contrário, ele vai iniciar uma sessão interativa.

Esta é a sintaxe do comando monkeyrunner:

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

A Tabela 1 explica os sinalizadores e argumentos do monkeyrunner.

Tabela 1. Sinalizações e argumentos do monkeyrunner.

Argumento Descrição
-plugin <plugin_jar> Opcional: esse argumento especifica um arquivo JAR que contém um plug-in para monkeyrunner. Para saber mais sobre os plug-ins monkeyrunner, consulte a seção Estender o monkeyrunner com plug-ins. Para especificar mais de um arquivo, inclua o argumento várias vezes.
<program_filename> Se você informar esse argumento, o comando monkeyrunner executará o conteúdo do arquivo como um programa Python. Caso contrário, o comando vai iniciar uma sessão interativa.
<program_options> (Opcional) Sinalizações e argumentos do programa em <program_file>. .

Ajuda integrada do monkeyrunner

Gere uma referência de API para monkeyrunner executando:

monkeyrunner help.py <format> <outfile>

Os argumentos são:

  • <format> é text para saída de texto simples ou html para saída HTML.
  • <outfile> é um nome qualificado pelo caminho para o arquivo de saída.

Ampliar o monkeyrunner com plug-ins

É possível estender a API monkeyrunner com classes que você escreve em Java e criar em um ou mais arquivos JAR. Você pode usar esse recurso para estender a API monkeyrunner com as próprias classes ou para estender as classes já existentes. Também é possível usar esse recurso para inicializar o ambiente monkeyrunner.

Para fornecer um plug-in para monkeyrunner, invoque o comando monkeyrunner com o argumento -plugin <plugin_jar> descrito na tabela 1.

No código do plug-in, você pode importar e estender as principais classes monkeyrunner MonkeyDevice, MonkeyImage e MonkeyRunner em com.android.monkeyrunner. Consulte a seção sobre a API monkeyrunner (em inglês).

Os plug-ins não dão acesso ao SDK do Android. Não é possível importar pacotes como com.android.app. Isso ocorre porque o monkeyrunner interage com o dispositivo ou emulador abaixo do nível das APIs do framework.

Classe de inicialização do plug-in

O arquivo JAR de um plug-in pode especificar uma classe instanciada antes do início do processamento do script. Para especificar essa classe, adicione a chave MonkeyRunnerStartupRunner ao manifesto do arquivo. Como valor, use o nome da classe a ser executada na inicialização. O snippet a seguir mostra como fazer isso em um script de compilação ant:

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


Para ter acesso ao ambiente de execução da ferramenta monkeyrunner, a classe de inicialização pode implementar com.google.common.base.Predicate<PythonInterpreter>. Por exemplo, a seguinte classe configura algumas variáveis no namespace padrão:

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