Exemplo de teste TF ponta a ponta

Este tutorial orienta você na criação de uma configuração de teste "hello world" da Trade Federation (Tradefed ou TF) e fornece uma introdução prática à estrutura do TF. A partir de um ambiente de desenvolvimento, você criará uma configuração simples e adicionará recursos.

O tutorial apresenta o processo de desenvolvimento de teste como um conjunto de exercícios, cada um consistindo em várias etapas, que demonstram como construir e refinar gradualmente sua configuração. Todo o código de amostra necessário para concluir a configuração do teste é fornecido e o título de cada exercício é anotado com uma letra descrevendo as funções envolvidas nessa etapa:

  • D para Desenvolvedor
  • eu de integrador
  • R para Test Runner

Depois de concluir o tutorial, você terá uma configuração de TF funcional e entenderá muitos conceitos importantes da estrutura do TF.

Configurar Federação Comercial

Para obter detalhes sobre como configurar o ambiente de desenvolvimento do TF, consulte Configuração da máquina . O restante deste tutorial pressupõe que você tenha um shell aberto que foi inicializado no ambiente TF.

Para simplificar, este tutorial ilustra a adição de uma configuração e suas classes à biblioteca principal da estrutura do TF. Isso pode ser estendido para desenvolver módulos fora da árvore de origem, compilando o JAR alimentado por comércio e, em seguida, compilando seus módulos nesse JAR.

Criar uma classe de teste (D)

Vamos criar um teste hello world que apenas despeja uma mensagem para stdout. Um teste de tradefed geralmente implementa a interface IRemoteTest . Aqui está uma implementação para o HelloWorldTest:

package com.android.tradefed.example;

import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.testtype.IRemoteTest;

public class HelloWorldTest implements IRemoteTest {
    @Override
    public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
        CLog.i("Hello, TF World!");
    }
}

Salve este código de amostra em <tree>/tools/tradefederation/core/src/com/android/tradefed/example/HelloWorldTest.java e reconstrua tradefed a partir de seu shell:

m -jN

Observe que CLog.i no exemplo acima é usado para direcionar a saída para o console. Mais informações sobre o login na Trade Federation são descritas em Logging (D, I, R) .

Se a compilação não for bem-sucedida, consulte a configuração da máquina para garantir que você não tenha perdido nenhuma etapa.

Criar uma configuração (I)

Os testes da Trade Federation tornam-se executáveis ​​criando um Configuration , um arquivo XML que instrui o tradefed sobre qual teste (ou testes) executar, bem como quais outros módulos executar e em que ordem.

Vamos criar uma nova configuração para nosso HelloWorldTest (observe o nome completo da classe HelloWorldTest):

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
</configuration>

Salve esses dados em um arquivo helloworld.xml em qualquer lugar do sistema de arquivos local (por exemplo /tmp/helloworld.xml ). O TF irá analisar o arquivo XML de configuração (também conhecido como config ), carregar a classe especificada usando reflexão, instanciá-la, convertê-la em um IRemoteTest e chamar seu método run .

Execute a configuração (R)

No shell, inicie o console tradefed:

tradefed.sh

Certifique-se de que um dispositivo esteja conectado à máquina host e visível para tradefed:

tf> list devices
Serial            State      Product   Variant   Build   Battery
004ad9880810a548  Available  mako      mako      JDQ39   100

As configurações podem ser executadas usando o comando run <config> do console. Tentar:

tf> run /tmp/helloworld.xml
05-12 13:19:36 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World!

Você deve ver "Hello, TF World!" saída no terminal.

Você pode confirmar que um comando foi executado usando list invocations ou li no prompt do console e não deve imprimir nada. Se os comandos estiverem em execução no momento, eles serão exibidos da seguinte maneira:

tf >l i
Command Id  Exec Time  Device       State
10          0m:00      [876X00GNG]  running stub on build(s) 'BuildInfo{bid=0, target=stub, serial=876X00GNG}'

Adicione a configuração ao classpath (D, I, R)

Para conveniência de implantação, você também pode agrupar configurações nos próprios JARs alimentados por comércio. Tradefed reconhece automaticamente todas as configurações colocadas em pastas de configuração no classpath.

Para ilustrar, mova o arquivo helloworld.xml para a biblioteca principal tradefed ( <tree>/tools/tradefederation/core/res/config/example/helloworld.xml ). Recrie o tradefed, reinicie o console do tradefed e peça ao tradefed para exibir a lista de configurações do caminho de classe:

tf> list configs
[…]
example/helloworld: Runs the hello world test

Agora você pode executar a configuração helloworld usando:

tf> run example/helloworld
05-12 13:21:21 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World!

Interagir com um dispositivo (D, R)

Até agora, nosso HelloWorldTest não está fazendo nada de interessante. A especialidade da Tradefed é executar testes usando dispositivos Android, então vamos adicionar um dispositivo Android ao teste.

Os testes podem obter uma referência a um dispositivo Android usando TestInformation , fornecido pela estrutura quando o método IRemoteTest#run é chamado.

Vamos modificar a mensagem de impressão HelloWorldTest para exibir o número de série do dispositivo:

@Override
public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber());
}

Agora reconstrua o tradefed e verifique a lista de dispositivos:

tradefed.sh
tf> list devices
Serial            State      Product   Variant   Build   Battery
004ad9880810a548  Available  mako      mako      JDQ39   100

Anote o número de série listado como Disponível ; esse é o dispositivo que deve ser alocado para HelloWorld:

tf> run example/helloworld
05-12 13:26:18 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World! I have device 004ad9880810a548

Você deve ver a nova mensagem de impressão exibindo o número de série do dispositivo.

Enviar resultados de teste (D)

IRemoteTest relata os resultados chamando métodos na instância ITestInvocationListener fornecida para o método #run . A própria estrutura do TF é responsável por relatar o início (via ITestInvocationListener#invocationStarted ) e o fim (via ITestInvocationListener#invocationEnded ) de cada Invocation.

Uma execução de teste é uma coleção lógica de testes. Para relatar resultados de teste, IRemoteTest é responsável por relatar o início de uma execução de teste, o início e o fim de cada teste e o final da execução de teste.

Aqui está a aparência da implementação HelloWorldTest com um único resultado de teste com falha.

@Override
public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber());

    TestDescription testId = new TestDescription("com.example.TestClassName", "sampleTest");
    listener.testRunStarted("helloworldrun", 1);
    listener.testStarted(testId);
    listener.testFailed(testId, "oh noes, test failed");
    listener.testEnded(testId, Collections.emptyMap());
    listener.testRunEnded(0, Collections.emptyMap());
}

O TF inclui várias implementações IRemoteTest que você pode reutilizar em vez de escrever do zero. Por exemplo, InstrumentationTest pode executar testes de um aplicativo Android remotamente em um dispositivo Android, analisar os resultados e encaminhá-los para o ITestInvocationListener ). Para obter detalhes, consulte Tipos de teste .

Armazenar resultados de teste (I)

A implementação padrão do ouvinte de teste para uma configuração de TF é TextResultReporter , que despeja os resultados de uma invocação para stdout. Para ilustrar, execute a configuração HelloWorldTest da seção anterior:

./tradefed.sh
tf> run example/helloworld
04-29 18:25:55 I/TestInvocation: Invocation was started with cmd: /tmp/helloworld.xml
04-29 18:25:55 I/TestInvocation: Starting invocation for 'stub' with '[ BuildInfo{bid=0, target=stub, serial=876X00GNG} on device '876X00GNG']
04-29 18:25:55 I/HelloWorldTest: Hello, TF World! I have device 876X00GNG
04-29 18:25:55 I/InvocationToJUnitResultForwarder: Running helloworldrun: 1 tests
04-29 18:25:55 W/InvocationToJUnitResultForwarder:
Test com.example.TestClassName#sampleTest failed with stack:
 oh noes, test failed
04-29 18:25:55 I/InvocationToJUnitResultForwarder: Run ended in 0 ms

Para armazenar os resultados de uma invocação em outro lugar, como em um arquivo, especifique uma implementação personalizada ITestInvocationListener usando a tag result_reporter em sua configuração.

O TF também inclui o ouvinte XmlResultReporter , que grava os resultados do teste em um arquivo XML em um formato semelhante ao usado pelo gravador ant JUnit XML. Para especificar o result_reporter na configuração, edite a configuração …/res/config/example/helloworld.xml :

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
    <result_reporter class="com.android.tradefed.result.XmlResultReporter" />
</configuration>

Agora reconstrua o tradefed e execute novamente a amostra hello world:

tf> run example/helloworld
05-16 21:07:07 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World! I have device 004ad9880810a548
05-16 21:07:07 I/XmlResultReporter: Saved device_logcat log to /tmp/0/inv_2991649128735283633/device_logcat_6999997036887173857.txt
05-16 21:07:07 I/XmlResultReporter: Saved host_log log to /tmp/0/inv_2991649128735283633/host_log_6307746032218561704.txt
05-16 21:07:07 I/XmlResultReporter: XML test result file generated at /tmp/0/inv_2991649128735283633/test_result_536358148261684076.xml. Total tests 1, Failed 1, Error 0

Observe a mensagem de log informando que um arquivo XML foi gerado; o arquivo gerado deve ficar assim:

<?xml version='1.0' encoding='UTF-8' ?>
<testsuite name="stub" tests="1" failures="1" errors="0" time="9" timestamp="2011-05-17T04:07:07" hostname="localhost">
  <properties />
  <testcase name="sampleTest" classname="com.example.TestClassName" time="0">
    <failure>oh noes, test failed
    </failure>
  </testcase>
</testsuite>

Você também pode escrever seus próprios ouvintes de invocação personalizados — eles simplesmente precisam implementar a interface ITestInvocationListener .

O Tradefed oferece suporte a vários ouvintes de invocação, para que você possa enviar resultados de teste para vários destinos independentes. Para fazer isso, basta especificar várias tags <result_reporter> em seu arquivo config.

Instalações de registro (D, I, R)

As instalações de registro do TF incluem a capacidade de:

  1. Capturar logs do dispositivo (também conhecido como device logcat)
  2. Registre logs da estrutura da Trade Federation em execução na máquina host (também conhecido como log do host)

A estrutura TF captura automaticamente o logcat do dispositivo alocado e o envia para o ouvinte de invocação para processamento. XmlResultReporter então salva o logcat do dispositivo capturado como um arquivo.

Os logs do host TF são relatados usando o wrapper CLog para a classe Log ddmlib. Vamos converter a chamada System.out.println anterior em HelloWorldTest para uma chamada CLog :

@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device %s", getDevice().getSerialNumber());

CLog manipula a interpolação de strings diretamente, semelhante a String.format . Quando você reconstruir e executar novamente o TF, deverá ver a mensagem de log em stdout:

tf> run example/helloworld
…
05-16 21:30:46 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548
…

Por padrão, tradefed envia mensagens de log do host para stdout . O TF também inclui uma implementação de log que grava mensagens em um arquivo: FileLogger . Para adicionar registro de arquivo, adicione uma tag logger à configuração, especificando o nome completo da classe de FileLogger :

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
    <result_reporter class="com.android.tradefed.result.XmlResultReporter" />
    <logger class="com.android.tradefed.log.FileLogger" />
</configuration>

Agora, reconstrua e execute o exemplo helloworld novamente:

tf >run example/helloworld
…
05-16 21:38:21 I/XmlResultReporter: Saved device_logcat log to /tmp/0/inv_6390011618174565918/device_logcat_1302097394309452308.txt
05-16 21:38:21 I/XmlResultReporter: Saved host_log log to /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt
…

A mensagem de log indica o caminho do log do host, que, quando visualizado, deve conter sua mensagem de log HelloWorldTest:

more /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt

Saída de exemplo:

…
05-16 21:38:21 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548

Opções de manuseio (D, I, R)

Objetos carregados de uma configuração de TF (também conhecidos como objetos de configuração ) também podem receber dados de argumentos de linha de comando por meio do uso da anotação @Option .

Para participar, uma classe de objeto de Configuração aplica a anotação @Option a um campo de membro e fornece a ele um nome exclusivo. Isso permite que o valor do campo de membro seja preenchido por meio de uma opção de linha de comando (e também adiciona automaticamente essa opção ao sistema de ajuda de configuração).

Nota: Nem todos os tipos de campo são suportados. Para obter uma descrição dos tipos com suporte, consulte OptionSetter .

Vamos adicionar uma @Option ao HelloWorldTest:

@Option(name="my_option",
        shortName='m',
        description="this is the option's help text",
        // always display this option in the default help text
        importance=Importance.ALWAYS)
private String mMyOption = "thisisthedefault";

Em seguida, vamos adicionar uma mensagem de log para exibir o valor da opção em HelloWorldTest para que possamos demonstrar que foi recebido corretamente:

@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
    …
    CLog.logAndDisplay(LogLevel.INFO, "I received option '%s'", mMyOption);

Por fim, reconstrua o TF e execute helloworld; você deve ver uma mensagem de log com o valor padrão my_option :

tf> run example/helloworld
…
05-24 18:30:05 I/HelloWorldTest: I received option 'thisisthedefault'

Passar valores da linha de comando

Passe um valor para my_option ; você deve ver my_option preenchido com esse valor:

tf> run example/helloworld --my_option foo
…
05-24 18:33:44 I/HelloWorldTest: I received option 'foo'

As configurações do TF também incluem um sistema de ajuda, que exibe automaticamente o texto de ajuda para os campos @Option . Experimente agora e você verá o texto de ajuda para my_option :

tf> run example/helloworld --help
Printing help for only the important options. To see help for all options, use the --help-all flag

  cmd_options options:
    --[no-]help          display the help text for the most important/critical options. Default: false.
    --[no-]help-all      display the full help text for all options. Default: false.
    --[no-]loop          keep running continuously. Default: false.

  test options:
    -m, --my_option      this is the option's help text Default: thisisthedefault.

  'file' logger options:
    --log-level-display  the minimum log level to display on stdout. Must be one of verbose, debug, info, warn, error, assert. Default: error.

Observe a mensagem sobre "imprimir apenas as opções importantes". Para reduzir a desordem da ajuda de opções, o TF usa o atributo Option#importance para determinar se deve mostrar um texto de ajuda de campo @Option específico quando --help é especificado. --help-all sempre mostra ajuda para todos os campos @Option , independentemente da importância. Para obter detalhes, consulte Option.Importance .

Passar valores de uma configuração

Você também pode especificar um valor de opção na configuração adicionando um elemento <option name="" value=""> . Teste usando helloworld.xml :

<test class="com.android.tradefed.example.HelloWorldTest" >
    <option name="my_option" value="fromxml" />
</test>

Recompilar e executar o helloworld agora deve produzir esta saída:

05-24 20:38:25 I/HelloWorldTest: I received option 'fromxml'

A ajuda de configuração também deve ser atualizada para indicar o valor padrão de my_option :

tf> run example/helloworld --help
  test options:
    -m, --my_option      this is the option's help text Default: fromxml.

Outros objetos de configuração incluídos na configuração helloworld, como FileLogger , também aceitam opções. A opção --log-level-display é interessante porque filtra os logs que aparecem no stdout. Anteriormente no tutorial, você deve ter notado a mensagem de log "Hello, TF World! I have device …' parou de ser exibida no stdout depois que passamos a usar FileLogger . Você pode aumentar a verbosidade do log no stdout passando no --log-level-display arg.

Tente isso agora e você deverá ver a mensagem de log 'I have device' reaparecer no stdout, além de ser registrado em um arquivo:

tf> run example/helloworld --log-level-display info
…
05-24 18:53:50 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548

Isso é tudo, pessoal!

Como um lembrete, se você estiver preso em alguma coisa, o código-fonte da Trade Federation tem muitas informações úteis que não são expostas na documentação. Se tudo mais falhar, tente perguntar no Google Group da plataforma Android , com "Trade Federation" no assunto da mensagem.

,

Este tutorial orienta você na criação de uma configuração de teste "hello world" da Trade Federation (Tradefed ou TF) e fornece uma introdução prática à estrutura do TF. A partir de um ambiente de desenvolvimento, você criará uma configuração simples e adicionará recursos.

O tutorial apresenta o processo de desenvolvimento de teste como um conjunto de exercícios, cada um consistindo em várias etapas, que demonstram como construir e refinar gradualmente sua configuração. Todo o código de amostra necessário para concluir a configuração do teste é fornecido e o título de cada exercício é anotado com uma letra descrevendo as funções envolvidas nessa etapa:

  • D para Desenvolvedor
  • eu de integrador
  • R para Test Runner

Depois de concluir o tutorial, você terá uma configuração de TF funcional e entenderá muitos conceitos importantes da estrutura do TF.

Configurar Federação Comercial

Para obter detalhes sobre como configurar o ambiente de desenvolvimento do TF, consulte Configuração da máquina . O restante deste tutorial pressupõe que você tenha um shell aberto que foi inicializado no ambiente TF.

Para simplificar, este tutorial ilustra a adição de uma configuração e suas classes à biblioteca principal da estrutura do TF. Isso pode ser estendido para desenvolver módulos fora da árvore de origem, compilando o JAR alimentado por comércio e, em seguida, compilando seus módulos nesse JAR.

Criar uma classe de teste (D)

Vamos criar um teste hello world que apenas despeja uma mensagem para stdout. Um teste de tradefed geralmente implementa a interface IRemoteTest . Aqui está uma implementação para o HelloWorldTest:

package com.android.tradefed.example;

import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.testtype.IRemoteTest;

public class HelloWorldTest implements IRemoteTest {
    @Override
    public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
        CLog.i("Hello, TF World!");
    }
}

Salve este código de amostra em <tree>/tools/tradefederation/core/src/com/android/tradefed/example/HelloWorldTest.java e reconstrua tradefed a partir de seu shell:

m -jN

Observe que CLog.i no exemplo acima é usado para direcionar a saída para o console. Mais informações sobre o login na Trade Federation são descritas em Logging (D, I, R) .

Se a compilação não for bem-sucedida, consulte a configuração da máquina para garantir que você não tenha perdido nenhuma etapa.

Criar uma configuração (I)

Os testes da Trade Federation tornam-se executáveis ​​criando um Configuration , um arquivo XML que instrui o tradefed sobre qual teste (ou testes) executar, bem como quais outros módulos executar e em que ordem.

Vamos criar uma nova configuração para nosso HelloWorldTest (observe o nome completo da classe HelloWorldTest):

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
</configuration>

Salve esses dados em um arquivo helloworld.xml em qualquer lugar do sistema de arquivos local (por exemplo /tmp/helloworld.xml ). O TF irá analisar o arquivo XML de configuração (também conhecido como config ), carregar a classe especificada usando reflexão, instanciá-la, convertê-la em um IRemoteTest e chamar seu método run .

Execute a configuração (R)

No shell, inicie o console tradefed:

tradefed.sh

Certifique-se de que um dispositivo esteja conectado à máquina host e visível para tradefed:

tf> list devices
Serial            State      Product   Variant   Build   Battery
004ad9880810a548  Available  mako      mako      JDQ39   100

As configurações podem ser executadas usando o comando run <config> do console. Tentar:

tf> run /tmp/helloworld.xml
05-12 13:19:36 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World!

Você deve ver "Hello, TF World!" saída no terminal.

Você pode confirmar que um comando foi executado usando list invocations ou li no prompt do console e não deve imprimir nada. Se os comandos estiverem em execução no momento, eles serão exibidos da seguinte maneira:

tf >l i
Command Id  Exec Time  Device       State
10          0m:00      [876X00GNG]  running stub on build(s) 'BuildInfo{bid=0, target=stub, serial=876X00GNG}'

Adicione a configuração ao classpath (D, I, R)

Para conveniência de implantação, você também pode agrupar configurações nos próprios JARs alimentados por comércio. Tradefed reconhece automaticamente todas as configurações colocadas em pastas de configuração no classpath.

Para ilustrar, mova o arquivo helloworld.xml para a biblioteca principal tradefed ( <tree>/tools/tradefederation/core/res/config/example/helloworld.xml ). Recrie o tradefed, reinicie o console do tradefed e peça ao tradefed para exibir a lista de configurações do caminho de classe:

tf> list configs
[…]
example/helloworld: Runs the hello world test

Agora você pode executar a configuração helloworld usando:

tf> run example/helloworld
05-12 13:21:21 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World!

Interagir com um dispositivo (D, R)

Até agora, nosso HelloWorldTest não está fazendo nada de interessante. A especialidade da Tradefed é executar testes usando dispositivos Android, então vamos adicionar um dispositivo Android ao teste.

Os testes podem obter uma referência a um dispositivo Android usando TestInformation , fornecido pela estrutura quando o método IRemoteTest#run é chamado.

Vamos modificar a mensagem de impressão HelloWorldTest para exibir o número de série do dispositivo:

@Override
public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber());
}

Agora reconstrua o tradefed e verifique a lista de dispositivos:

tradefed.sh
tf> list devices
Serial            State      Product   Variant   Build   Battery
004ad9880810a548  Available  mako      mako      JDQ39   100

Anote o número de série listado como Disponível ; esse é o dispositivo que deve ser alocado para HelloWorld:

tf> run example/helloworld
05-12 13:26:18 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World! I have device 004ad9880810a548

Você deve ver a nova mensagem de impressão exibindo o número de série do dispositivo.

Enviar resultados de teste (D)

IRemoteTest relata os resultados chamando métodos na instância ITestInvocationListener fornecida para o método #run . A própria estrutura do TF é responsável por relatar o início (via ITestInvocationListener#invocationStarted ) e o fim (via ITestInvocationListener#invocationEnded ) de cada Invocation.

Uma execução de teste é uma coleção lógica de testes. Para relatar resultados de teste, IRemoteTest é responsável por relatar o início de uma execução de teste, o início e o fim de cada teste e o final da execução de teste.

Aqui está a aparência da implementação HelloWorldTest com um único resultado de teste com falha.

@Override
public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber());

    TestDescription testId = new TestDescription("com.example.TestClassName", "sampleTest");
    listener.testRunStarted("helloworldrun", 1);
    listener.testStarted(testId);
    listener.testFailed(testId, "oh noes, test failed");
    listener.testEnded(testId, Collections.emptyMap());
    listener.testRunEnded(0, Collections.emptyMap());
}

O TF inclui várias implementações IRemoteTest que você pode reutilizar em vez de escrever do zero. Por exemplo, InstrumentationTest pode executar testes de um aplicativo Android remotamente em um dispositivo Android, analisar os resultados e encaminhá-los para o ITestInvocationListener ). Para obter detalhes, consulte Tipos de teste .

Armazenar resultados de teste (I)

A implementação padrão do ouvinte de teste para uma configuração de TF é TextResultReporter , que despeja os resultados de uma invocação para stdout. Para ilustrar, execute a configuração HelloWorldTest da seção anterior:

./tradefed.sh
tf> run example/helloworld
04-29 18:25:55 I/TestInvocation: Invocation was started with cmd: /tmp/helloworld.xml
04-29 18:25:55 I/TestInvocation: Starting invocation for 'stub' with '[ BuildInfo{bid=0, target=stub, serial=876X00GNG} on device '876X00GNG']
04-29 18:25:55 I/HelloWorldTest: Hello, TF World! I have device 876X00GNG
04-29 18:25:55 I/InvocationToJUnitResultForwarder: Running helloworldrun: 1 tests
04-29 18:25:55 W/InvocationToJUnitResultForwarder:
Test com.example.TestClassName#sampleTest failed with stack:
 oh noes, test failed
04-29 18:25:55 I/InvocationToJUnitResultForwarder: Run ended in 0 ms

Para armazenar os resultados de uma invocação em outro lugar, como em um arquivo, especifique uma implementação personalizada ITestInvocationListener usando a tag result_reporter em sua configuração.

O TF também inclui o ouvinte XmlResultReporter , que grava os resultados do teste em um arquivo XML em um formato semelhante ao usado pelo gravador ant JUnit XML. Para especificar o result_reporter na configuração, edite a configuração …/res/config/example/helloworld.xml :

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
    <result_reporter class="com.android.tradefed.result.XmlResultReporter" />
</configuration>

Agora reconstrua o tradefed e execute novamente a amostra hello world:

tf> run example/helloworld
05-16 21:07:07 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World! I have device 004ad9880810a548
05-16 21:07:07 I/XmlResultReporter: Saved device_logcat log to /tmp/0/inv_2991649128735283633/device_logcat_6999997036887173857.txt
05-16 21:07:07 I/XmlResultReporter: Saved host_log log to /tmp/0/inv_2991649128735283633/host_log_6307746032218561704.txt
05-16 21:07:07 I/XmlResultReporter: XML test result file generated at /tmp/0/inv_2991649128735283633/test_result_536358148261684076.xml. Total tests 1, Failed 1, Error 0

Observe a mensagem de log informando que um arquivo XML foi gerado; o arquivo gerado deve ficar assim:

<?xml version='1.0' encoding='UTF-8' ?>
<testsuite name="stub" tests="1" failures="1" errors="0" time="9" timestamp="2011-05-17T04:07:07" hostname="localhost">
  <properties />
  <testcase name="sampleTest" classname="com.example.TestClassName" time="0">
    <failure>oh noes, test failed
    </failure>
  </testcase>
</testsuite>

Você também pode escrever seus próprios ouvintes de invocação personalizados — eles simplesmente precisam implementar a interface ITestInvocationListener .

O Tradefed oferece suporte a vários ouvintes de invocação, para que você possa enviar resultados de teste para vários destinos independentes. Para fazer isso, basta especificar várias tags <result_reporter> em seu arquivo config.

Instalações de registro (D, I, R)

As instalações de registro do TF incluem a capacidade de:

  1. Capturar logs do dispositivo (também conhecido como device logcat)
  2. Registre logs da estrutura da Trade Federation em execução na máquina host (também conhecido como log do host)

A estrutura TF captura automaticamente o logcat do dispositivo alocado e o envia para o ouvinte de invocação para processamento. XmlResultReporter então salva o logcat do dispositivo capturado como um arquivo.

Os logs do host TF são relatados usando o wrapper CLog para a classe Log ddmlib. Vamos converter a chamada System.out.println anterior em HelloWorldTest para uma chamada CLog :

@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device %s", getDevice().getSerialNumber());

CLog manipula a interpolação de strings diretamente, semelhante a String.format . Quando você reconstruir e executar novamente o TF, deverá ver a mensagem de log em stdout:

tf> run example/helloworld
…
05-16 21:30:46 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548
…

Por padrão, tradefed envia mensagens de log do host para stdout . O TF também inclui uma implementação de log que grava mensagens em um arquivo: FileLogger . Para adicionar registro de arquivo, adicione uma tag logger à configuração, especificando o nome completo da classe de FileLogger :

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
    <result_reporter class="com.android.tradefed.result.XmlResultReporter" />
    <logger class="com.android.tradefed.log.FileLogger" />
</configuration>

Agora, reconstrua e execute o exemplo helloworld novamente:

tf >run example/helloworld
…
05-16 21:38:21 I/XmlResultReporter: Saved device_logcat log to /tmp/0/inv_6390011618174565918/device_logcat_1302097394309452308.txt
05-16 21:38:21 I/XmlResultReporter: Saved host_log log to /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt
…

A mensagem de log indica o caminho do log do host, que, quando visualizado, deve conter sua mensagem de log HelloWorldTest:

more /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt

Saída de exemplo:

…
05-16 21:38:21 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548

Opções de manuseio (D, I, R)

Objetos carregados de uma configuração de TF (também conhecidos como objetos de configuração ) também podem receber dados de argumentos de linha de comando por meio do uso da anotação @Option .

Para participar, uma classe de objeto de Configuração aplica a anotação @Option a um campo de membro e fornece a ele um nome exclusivo. Isso permite que o valor do campo de membro seja preenchido por meio de uma opção de linha de comando (e também adiciona automaticamente essa opção ao sistema de ajuda de configuração).

Nota: Nem todos os tipos de campo são suportados. Para obter uma descrição dos tipos com suporte, consulte OptionSetter .

Vamos adicionar uma @Option ao HelloWorldTest:

@Option(name="my_option",
        shortName='m',
        description="this is the option's help text",
        // always display this option in the default help text
        importance=Importance.ALWAYS)
private String mMyOption = "thisisthedefault";

Em seguida, vamos adicionar uma mensagem de log para exibir o valor da opção em HelloWorldTest para que possamos demonstrar que foi recebido corretamente:

@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
    …
    CLog.logAndDisplay(LogLevel.INFO, "I received option '%s'", mMyOption);

Por fim, reconstrua o TF e execute helloworld; você deve ver uma mensagem de log com o valor padrão my_option :

tf> run example/helloworld
…
05-24 18:30:05 I/HelloWorldTest: I received option 'thisisthedefault'

Passar valores da linha de comando

Passe um valor para my_option ; você deve ver my_option preenchido com esse valor:

tf> run example/helloworld --my_option foo
…
05-24 18:33:44 I/HelloWorldTest: I received option 'foo'

As configurações do TF também incluem um sistema de ajuda, que exibe automaticamente o texto de ajuda para os campos @Option . Experimente agora e você verá o texto de ajuda para my_option :

tf> run example/helloworld --help
Printing help for only the important options. To see help for all options, use the --help-all flag

  cmd_options options:
    --[no-]help          display the help text for the most important/critical options. Default: false.
    --[no-]help-all      display the full help text for all options. Default: false.
    --[no-]loop          keep running continuously. Default: false.

  test options:
    -m, --my_option      this is the option's help text Default: thisisthedefault.

  'file' logger options:
    --log-level-display  the minimum log level to display on stdout. Must be one of verbose, debug, info, warn, error, assert. Default: error.

Observe a mensagem sobre "imprimir apenas as opções importantes". Para reduzir a desordem da ajuda de opções, o TF usa o atributo Option#importance para determinar se deve mostrar um texto de ajuda de campo @Option específico quando --help é especificado. --help-all sempre mostra ajuda para todos os campos @Option , independentemente da importância. Para obter detalhes, consulte Option.Importance .

Passar valores de uma configuração

Você também pode especificar um valor de opção na configuração adicionando um elemento <option name="" value=""> . Teste usando helloworld.xml :

<test class="com.android.tradefed.example.HelloWorldTest" >
    <option name="my_option" value="fromxml" />
</test>

Recompilar e executar o helloworld agora deve produzir esta saída:

05-24 20:38:25 I/HelloWorldTest: I received option 'fromxml'

A ajuda de configuração também deve ser atualizada para indicar o valor padrão de my_option :

tf> run example/helloworld --help
  test options:
    -m, --my_option      this is the option's help text Default: fromxml.

Outros objetos de configuração incluídos na configuração helloworld, como FileLogger , também aceitam opções. A opção --log-level-display é interessante porque filtra os logs que aparecem no stdout. Anteriormente no tutorial, você deve ter notado a mensagem de log "Hello, TF World! I have device …' parou de ser exibida no stdout depois que passamos a usar FileLogger . Você pode aumentar a verbosidade do log no stdout passando no --log-level-display arg.

Tente isso agora e você deverá ver a mensagem de log 'I have device' reaparecer no stdout, além de ser registrado em um arquivo:

tf> run example/helloworld --log-level-display info
…
05-24 18:53:50 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548

Isso é tudo, pessoal!

Como um lembrete, se você estiver preso em alguma coisa, o código-fonte da Trade Federation tem muitas informações úteis que não são expostas na documentação. Se tudo mais falhar, tente perguntar no Google Group da plataforma Android , com "Trade Federation" no assunto da mensagem.

,

Este tutorial orienta você na criação de uma configuração de teste "hello world" da Trade Federation (Tradefed ou TF) e fornece uma introdução prática à estrutura do TF. A partir de um ambiente de desenvolvimento, você criará uma configuração simples e adicionará recursos.

O tutorial apresenta o processo de desenvolvimento de teste como um conjunto de exercícios, cada um consistindo em várias etapas, que demonstram como construir e refinar gradualmente sua configuração. Todo o código de amostra necessário para concluir a configuração do teste é fornecido e o título de cada exercício é anotado com uma letra descrevendo as funções envolvidas nessa etapa:

  • D para Desenvolvedor
  • eu de integrador
  • R para Test Runner

Depois de concluir o tutorial, você terá uma configuração de TF funcional e entenderá muitos conceitos importantes da estrutura do TF.

Configurar Federação Comercial

Para obter detalhes sobre como configurar o ambiente de desenvolvimento do TF, consulte Configuração da máquina . O restante deste tutorial pressupõe que você tenha um shell aberto que foi inicializado no ambiente TF.

Para simplificar, este tutorial ilustra a adição de uma configuração e suas classes à biblioteca principal da estrutura do TF. Isso pode ser estendido para desenvolver módulos fora da árvore de origem, compilando o JAR alimentado por comércio e, em seguida, compilando seus módulos nesse JAR.

Criar uma classe de teste (D)

Vamos criar um teste hello world que apenas despeja uma mensagem para stdout. Um teste de tradefed geralmente implementa a interface IRemoteTest . Aqui está uma implementação para o HelloWorldTest:

package com.android.tradefed.example;

import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.testtype.IRemoteTest;

public class HelloWorldTest implements IRemoteTest {
    @Override
    public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
        CLog.i("Hello, TF World!");
    }
}

Salve este código de amostra em <tree>/tools/tradefederation/core/src/com/android/tradefed/example/HelloWorldTest.java e reconstrua tradefed a partir de seu shell:

m -jN

Observe que CLog.i no exemplo acima é usado para direcionar a saída para o console. Mais informações sobre o login na Trade Federation são descritas em Logging (D, I, R) .

Se a compilação não for bem-sucedida, consulte a configuração da máquina para garantir que você não tenha perdido nenhuma etapa.

Criar uma configuração (I)

Os testes da Trade Federation tornam-se executáveis ​​criando um Configuration , um arquivo XML que instrui o tradefed sobre qual teste (ou testes) executar, bem como quais outros módulos executar e em que ordem.

Vamos criar uma nova configuração para nosso HelloWorldTest (observe o nome completo da classe HelloWorldTest):

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
</configuration>

Salve esses dados em um arquivo helloworld.xml em qualquer lugar do sistema de arquivos local (por exemplo /tmp/helloworld.xml ). O TF irá analisar o arquivo XML de configuração (também conhecido como config ), carregar a classe especificada usando reflexão, instanciá-la, convertê-la em um IRemoteTest e chamar seu método run .

Execute a configuração (R)

No shell, inicie o console tradefed:

tradefed.sh

Certifique-se de que um dispositivo esteja conectado à máquina host e visível para tradefed:

tf> list devices
Serial            State      Product   Variant   Build   Battery
004ad9880810a548  Available  mako      mako      JDQ39   100

As configurações podem ser executadas usando o comando run <config> do console. Tentar:

tf> run /tmp/helloworld.xml
05-12 13:19:36 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World!

Você deve ver "Hello, TF World!" saída no terminal.

Você pode confirmar que um comando foi executado usando list invocations ou li no prompt do console e não deve imprimir nada. Se os comandos estiverem em execução no momento, eles serão exibidos da seguinte maneira:

tf >l i
Command Id  Exec Time  Device       State
10          0m:00      [876X00GNG]  running stub on build(s) 'BuildInfo{bid=0, target=stub, serial=876X00GNG}'

Adicione a configuração ao classpath (D, I, R)

Para conveniência de implantação, você também pode agrupar configurações nos próprios JARs alimentados por comércio. Tradefed reconhece automaticamente todas as configurações colocadas em pastas de configuração no classpath.

Para ilustrar, mova o arquivo helloworld.xml para a biblioteca principal tradefed ( <tree>/tools/tradefederation/core/res/config/example/helloworld.xml ). Recrie o tradefed, reinicie o console do tradefed e peça ao tradefed para exibir a lista de configurações do caminho de classe:

tf> list configs
[…]
example/helloworld: Runs the hello world test

Agora você pode executar a configuração helloworld usando:

tf> run example/helloworld
05-12 13:21:21 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World!

Interagir com um dispositivo (D, R)

Até agora, nosso HelloWorldTest não está fazendo nada de interessante. A especialidade da Tradefed é executar testes usando dispositivos Android, então vamos adicionar um dispositivo Android ao teste.

Os testes podem obter uma referência a um dispositivo Android usando TestInformation , fornecido pela estrutura quando o método IRemoteTest#run é chamado.

Vamos modificar a mensagem de impressão HelloWorldTest para exibir o número de série do dispositivo:

@Override
public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber());
}

Agora reconstrua o tradefed e verifique a lista de dispositivos:

tradefed.sh
tf> list devices
Serial            State      Product   Variant   Build   Battery
004ad9880810a548  Available  mako      mako      JDQ39   100

Anote o número de série listado como Disponível ; esse é o dispositivo que deve ser alocado para HelloWorld:

tf> run example/helloworld
05-12 13:26:18 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World! I have device 004ad9880810a548

Você deve ver a nova mensagem de impressão exibindo o número de série do dispositivo.

Enviar resultados de teste (D)

IRemoteTest relata os resultados chamando métodos na instância ITestInvocationListener fornecida para o método #run . A própria estrutura do TF é responsável por relatar o início (via ITestInvocationListener#invocationStarted ) e o fim (via ITestInvocationListener#invocationEnded ) de cada Invocation.

Uma execução de teste é uma coleção lógica de testes. Para relatar resultados de teste, IRemoteTest é responsável por relatar o início de uma execução de teste, o início e o fim de cada teste e o final da execução de teste.

Aqui está a aparência da implementação HelloWorldTest com um único resultado de teste com falha.

@Override
public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber());

    TestDescription testId = new TestDescription("com.example.TestClassName", "sampleTest");
    listener.testRunStarted("helloworldrun", 1);
    listener.testStarted(testId);
    listener.testFailed(testId, "oh noes, test failed");
    listener.testEnded(testId, Collections.emptyMap());
    listener.testRunEnded(0, Collections.emptyMap());
}

O TF inclui várias implementações IRemoteTest que você pode reutilizar em vez de escrever do zero. Por exemplo, InstrumentationTest pode executar testes de um aplicativo Android remotamente em um dispositivo Android, analisar os resultados e encaminhá-los para o ITestInvocationListener ). Para obter detalhes, consulte Tipos de teste .

Armazenar resultados de teste (I)

A implementação padrão do ouvinte de teste para uma configuração de TF é TextResultReporter , que despeja os resultados de uma invocação para stdout. Para ilustrar, execute a configuração HelloWorldTest da seção anterior:

./tradefed.sh
tf> run example/helloworld
04-29 18:25:55 I/TestInvocation: Invocation was started with cmd: /tmp/helloworld.xml
04-29 18:25:55 I/TestInvocation: Starting invocation for 'stub' with '[ BuildInfo{bid=0, target=stub, serial=876X00GNG} on device '876X00GNG']
04-29 18:25:55 I/HelloWorldTest: Hello, TF World! I have device 876X00GNG
04-29 18:25:55 I/InvocationToJUnitResultForwarder: Running helloworldrun: 1 tests
04-29 18:25:55 W/InvocationToJUnitResultForwarder:
Test com.example.TestClassName#sampleTest failed with stack:
 oh noes, test failed
04-29 18:25:55 I/InvocationToJUnitResultForwarder: Run ended in 0 ms

Para armazenar os resultados de uma invocação em outro lugar, como em um arquivo, especifique uma implementação personalizada ITestInvocationListener usando a tag result_reporter em sua configuração.

O TF também inclui o ouvinte XmlResultReporter , que grava os resultados do teste em um arquivo XML em um formato semelhante ao usado pelo gravador ant JUnit XML. Para especificar o result_reporter na configuração, edite a configuração …/res/config/example/helloworld.xml :

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
    <result_reporter class="com.android.tradefed.result.XmlResultReporter" />
</configuration>

Agora reconstrua o tradefed e execute novamente a amostra hello world:

tf> run example/helloworld
05-16 21:07:07 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548
Hello, TF World! I have device 004ad9880810a548
05-16 21:07:07 I/XmlResultReporter: Saved device_logcat log to /tmp/0/inv_2991649128735283633/device_logcat_6999997036887173857.txt
05-16 21:07:07 I/XmlResultReporter: Saved host_log log to /tmp/0/inv_2991649128735283633/host_log_6307746032218561704.txt
05-16 21:07:07 I/XmlResultReporter: XML test result file generated at /tmp/0/inv_2991649128735283633/test_result_536358148261684076.xml. Total tests 1, Failed 1, Error 0

Observe a mensagem de log informando que um arquivo XML foi gerado; o arquivo gerado deve ficar assim:

<?xml version='1.0' encoding='UTF-8' ?>
<testsuite name="stub" tests="1" failures="1" errors="0" time="9" timestamp="2011-05-17T04:07:07" hostname="localhost">
  <properties />
  <testcase name="sampleTest" classname="com.example.TestClassName" time="0">
    <failure>oh noes, test failed
    </failure>
  </testcase>
</testsuite>

Você também pode escrever seus próprios ouvintes de invocação personalizados — eles simplesmente precisam implementar a interface ITestInvocationListener .

O Tradefed oferece suporte a vários ouvintes de invocação, para que você possa enviar resultados de teste para vários destinos independentes. Para fazer isso, basta especificar várias tags <result_reporter> em seu arquivo config.

Instalações de registro (D, I, R)

As instalações de registro do TF incluem a capacidade de:

  1. Capturar logs do dispositivo (também conhecido como device logcat)
  2. Registre logs da estrutura da Trade Federation em execução na máquina host (também conhecido como log do host)

A estrutura TF captura automaticamente o logcat do dispositivo alocado e o envia para o ouvinte de invocação para processamento. XmlResultReporter então salva o logcat do dispositivo capturado como um arquivo.

Os logs do host TF são relatados usando o wrapper CLog para a classe Log ddmlib. Vamos converter a chamada System.out.println anterior em HelloWorldTest para uma chamada CLog :

@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device %s", getDevice().getSerialNumber());

CLog manipula a interpolação de strings diretamente, semelhante a String.format . Quando você reconstruir e executar novamente o TF, deverá ver a mensagem de log em stdout:

tf> run example/helloworld
…
05-16 21:30:46 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548
…

Por padrão, tradefed envia mensagens de log do host para stdout . O TF também inclui uma implementação de log que grava mensagens em um arquivo: FileLogger . Para adicionar registro de arquivo, adicione uma tag logger à configuração, especificando o nome completo da classe de FileLogger :

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
    <result_reporter class="com.android.tradefed.result.XmlResultReporter" />
    <logger class="com.android.tradefed.log.FileLogger" />
</configuration>

Agora, reconstrua e execute o exemplo helloworld novamente:

tf >run example/helloworld
…
05-16 21:38:21 I/XmlResultReporter: Saved device_logcat log to /tmp/0/inv_6390011618174565918/device_logcat_1302097394309452308.txt
05-16 21:38:21 I/XmlResultReporter: Saved host_log log to /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt
…

A mensagem de log indica o caminho do log do host, que, quando visualizado, deve conter sua mensagem de log HelloWorldTest:

more /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt

Saída de exemplo:

…
05-16 21:38:21 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548

Opções de manuseio (D, I, R)

Objetos carregados de uma configuração de TF (também conhecidos como objetos de configuração ) também podem receber dados de argumentos de linha de comando por meio do uso da anotação @Option .

Para participar, uma classe de objeto de Configuração aplica a anotação @Option a um campo de membro e fornece a ele um nome exclusivo. Isso permite que o valor do campo de membro seja preenchido por meio de uma opção de linha de comando (e também adiciona automaticamente essa opção ao sistema de ajuda de configuração).

Nota: Nem todos os tipos de campo são suportados. Para obter uma descrição dos tipos com suporte, consulte OptionSetter .

Vamos adicionar uma @Option ao HelloWorldTest:

@Option(name="my_option",
        shortName='m',
        description="this is the option's help text",
        // always display this option in the default help text
        importance=Importance.ALWAYS)
private String mMyOption = "thisisthedefault";

Em seguida, vamos adicionar uma mensagem de log para exibir o valor da opção em HelloWorldTest para que possamos demonstrar que foi recebido corretamente:

@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
    …
    CLog.logAndDisplay(LogLevel.INFO, "I received option '%s'", mMyOption);

Por fim, reconstrua o TF e execute helloworld; você deve ver uma mensagem de log com o valor padrão my_option :

tf> run example/helloworld
…
05-24 18:30:05 I/HelloWorldTest: I received option 'thisisthedefault'

Passar valores da linha de comando

Passe um valor para my_option ; você deve ver my_option preenchido com esse valor:

tf> run example/helloworld --my_option foo
…
05-24 18:33:44 I/HelloWorldTest: I received option 'foo'

As configurações do TF também incluem um sistema de ajuda, que exibe automaticamente o texto de ajuda para os campos @Option . Experimente agora e você verá o texto de ajuda para my_option :

tf> run example/helloworld --help
Printing help for only the important options. To see help for all options, use the --help-all flag

  cmd_options options:
    --[no-]help          display the help text for the most important/critical options. Default: false.
    --[no-]help-all      display the full help text for all options. Default: false.
    --[no-]loop          keep running continuously. Default: false.

  test options:
    -m, --my_option      this is the option's help text Default: thisisthedefault.

  'file' logger options:
    --log-level-display  the minimum log level to display on stdout. Must be one of verbose, debug, info, warn, error, assert. Default: error.

Observe a mensagem sobre "imprimir apenas as opções importantes". Para reduzir a desordem da ajuda de opções, o TF usa o atributo Option#importance para determinar se deve mostrar um texto de ajuda de campo @Option específico quando --help é especificado. --help-all sempre mostra ajuda para todos os campos @Option , independentemente da importância. Para obter detalhes, consulte Option.Importance .

Passar valores de uma configuração

Você também pode especificar um valor de opção na configuração adicionando um elemento <option name="" value=""> . Teste usando helloworld.xml :

<test class="com.android.tradefed.example.HelloWorldTest" >
    <option name="my_option" value="fromxml" />
</test>

Recompilar e executar o helloworld agora deve produzir esta saída:

05-24 20:38:25 I/HelloWorldTest: I received option 'fromxml'

A ajuda de configuração também deve ser atualizada para indicar o valor padrão de my_option :

tf> run example/helloworld --help
  test options:
    -m, --my_option      this is the option's help text Default: fromxml.

Outros objetos de configuração incluídos na configuração helloworld, como FileLogger , também aceitam opções. A opção --log-level-display é interessante porque filtra os logs que aparecem no stdout. Anteriormente no tutorial, você deve ter notado a mensagem de log "Hello, TF World! I have device …' deixou de ser exibida no stdout depois que passamos a usar FileLogger . Você pode aumentar a verbosidade do log no stdout passando no --log-level-display arg.

Tente isso agora e você deverá ver a mensagem de log 'I have device' reaparecer no stdout, além de ser registrado em um arquivo:

tf> run example/helloworld --log-level-display info
…
05-24 18:53:50 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548

Isso é tudo, pessoal!

Como um lembrete, se você estiver preso em alguma coisa, o código-fonte da Trade Federation tem muitas informações úteis que não são expostas na documentação. Se tudo mais falhar, tente perguntar no Google Group da plataforma Android , com "Trade Federation" no assunto da mensagem.