monkeyrunner

A ferramenta monkeyrunner disponibiliza uma API para criar programas que controlam um dispositivo ou emulador Android a partir de fora do código Android. Com o monkeyrunner, é possível criar um programa em Python que instala um aplicativo para 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. A ferramenta monkeyrunner é projetada principalmente para testar aplicativos e dispositivos no nível funcional/estrutural e para executar pacotes de testes de unidade. Entretanto, você pode usá-la para outras finalidades.

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 os seguintes recursos exclusivos para testes no 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 o teste automatizado completo de um aplicativo Android. Informe valores de entrada com pressionamentos de tecla ou eventos de toque e veja os resultados na forma de capturas de tela.
  • Teste de regressão: o monkeyrunner pode testar a estabilidade de um aplicativo executando-o e comparando as capturas de tela de saída com um conjunto de capturas de tela conhecidas como corretas.
  • Automação extensível: como o monkeyrunner é um kit de ferramentas de API, você pode desenvolver um sistema inteiro 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. Essa ação é descrita em mais detalhes na seção Como 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 facilmente 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
# 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')

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 exibir 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 aplicativo. Também é possível usar essa classe 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 declaração Python from:

from com.android.monkeyrunner import <module>

em que <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 a partir de um arquivo ou inserir declaraçõ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 executará o conteúdo do arquivo como um programa Python. Caso contrário, ele iniciará uma sessão interativa.

A sintaxe do comando monkeyrunner é

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

A Tabela 1 explica os sinalizadores e argumentos.

Tabela 1. Sinalizações e argumentos 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 Como 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. Se o argumento não for informado, o comando iniciará uma sessão interativa.
<program_options> Opcional: sinalizadores e argumentos para o 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.

Estender o Monkeyrunner com plug-ins

É possível estender a API monkeyrunner com as classes escritas na linguagem de programação Java e realizar a compilação 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 API monkeyrunner.

Observe que 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 .jar. O valor precisa ser o nome da classe a ser executada na inicialização. O snippet a seguir mostra como fazer isso com 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 do 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;
    }
}