Neste tutorial, orientamos você na criação de um "Hello World" Federação comercial (Tradefed ou TF) e oferece uma introdução prática ao TF de análise de dados em nuvem. Em um ambiente de desenvolvimento, você vai criar um configuração e adicionar recursos.
O tutorial apresenta o processo de desenvolvimento de testes como um conjunto de exercícios, cada uma composta de várias etapas, que demonstram como construir e refinar a configuração. Todo o exemplo de código necessário para concluir o teste é fornecida, e o título de cada exercício é anotado com um que descreve os papéis envolvidos nessa etapa:
- D para Desenvolvedor
- I para integrador
- R para Executor de testes
Depois de concluir o tutorial, você terá uma configuração do TF em funcionamento. e entender vários conceitos importantes no framework do TF.
Configurar a Trade Federation
Para detalhes sobre como configurar o ambiente de desenvolvimento do TF, consulte Máquina Configuração. O restante deste tutorial pressupõe que você tem um shell aberto que foi inicializado no ambiente TF.
Para simplificar, este tutorial ilustra como adicionar uma configuração e seus classes para a biblioteca principal do framework do TF. Isso pode ser estendido ao desenvolvimento fora da árvore de origem compilando o JAR comercializado e, em seguida, compilando seus módulos com esse JAR.
Criar uma classe de teste (D)
Vamos criar um teste "Hello World" que envia uma mensagem para a stdout. Um teste negociado geralmente implementa a IRemoteTest (link em inglês) interface gráfica do usuário. Confira uma implementação do 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!"); } }
Salvar este exemplo de código em
<tree>/tools/tradefederation/core/src/com/android/tradefed/example/HelloWorldTest.java
e recompilar o comércio a partir do shell:
m -jN
Observe que CLog.i
no exemplo acima é usado para direcionar a saída para o console. Mais
informações sobre login na Trade Federation estão descritas em Logging (D, I, R).
Se o build não for bem-sucedido, consulte Máquina Configure para não perder nenhuma etapa.
Criar uma configuração (I)
Os testes da Trade Federation são executados criando uma Configuration, um arquivo XML que instrui o valor (ou testes) para executar, bem como quais outros módulos executar e em que ordem.
Vamos criar uma nova configuração para o HelloWorldTest. Observe que nome do 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 da sua rede local
do sistema de arquivos (por exemplo, /tmp/helloworld.xml
). o TF vai analisar
Arquivo XML de configuração (também conhecido como config), carregue a classe especificada usando
reflexão, instanciar, transmitir para um IRemoteTest
e chamar o
método run
.
Executar a configuração (R)
No shell, inicie o console do Tradefed:
tradefed.sh
Verifique se um dispositivo está conectado à máquina host e visível para troca:
tf> list devices Serial State Product Variant Build Battery 004ad9880810a548 Available mako mako JDQ39 100
As configurações podem ser executadas usando o run <config>
comando do console do Cloud. Tente:
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ê verá "Hello, TF World!" no terminal.
Confirme se um comando já foi executado usando list invocations
ou
l i
no prompt do console. Ele não exibirá nada. Se os comandos estiverem
em execução, elas são exibidas da seguinte forma:
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}'
Adicionar a configuração ao caminho de classe (D, I, R)
Para facilitar a implantação, você também pode agrupar configurações no pacote os próprios JARs. O Tradefed reconhece automaticamente todas as configurações colocadas em config no caminho de classe.
Para ilustrar, mova o arquivo helloworld.xml
para a tabela
biblioteca principal
<tree>/tools/tradefederation/core/res/config/example/helloworld.xml
).
Recrie o Tradefed, reinicie o console negociado e peça para o Tradefed mostrar
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 fez nada interessante. da Tradefed. é executar testes usando dispositivos Android. Por isso, vamos adicionar um dispositivo para o teste.
Os testes podem receber uma referência a um dispositivo Android usando TestInformation
, fornecido
pelo framework quando o método IRemoteTest#run
é chamado.
Vamos modificar a mensagem de impressão HelloWorldTest para mostrar o número de série dispositivo:
@Override public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException { CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber()); }
Agora, recrie 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. que é o dispositivo que será alocado para o 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ê verá a nova mensagem de impressão com o número de série do dispositivo.
Enviar os resultados do teste (D)
IRemoteTest
gera relatórios de resultados chamando métodos na
ITestInvocationListener.
fornecida ao método #run
. O framework do TF é
responsável por informar o início (via
ITestInvocationListener#invocationStarted).
e terminar (via
ITestInvocationListener#invocationEnded).
de cada invocação.
Uma execução de teste é uma coleção lógica de testes. Para relatar os resultados do 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 fim da execução do teste.
Veja como pode ser a implementação do HelloWorldTest com uma única resultado do 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 de IRemoteTest
que podem ser reutilizadas
em vez de escrever o seu do zero. Por exemplo:
InstrumentationTest (em inglês)
pode executar os testes de um aplicativo Android remotamente em um dispositivo Android, analisar o
resultados e encaminhe esses resultados para ITestInvocationListener
).
Para mais detalhes, consulte
Teste
Tipos.
Armazenar resultados de testes (I)
A implementação padrão do listener de teste para a configuração do TF é TextResultReporter; que despeja os resultados de uma invocação em stdout. Para ilustrar, execute o comando 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 um
implementação personalizada de ITestInvocationListener
usando o
tag result_reporter
na sua configuração.
O TF também inclui
XmlResultReporter (link em inglês)
que grava os resultados do teste em um arquivo XML em um formato similar ao
usado pelo gravador XML JUnit ant. Para especificar o result_reporter na
de configuração, edite …/res/config/example/helloworld.xml
configuração:
<configuration description="Runs the hello world test"> <test class="com.android.tradefed.example.HelloWorldTest" /> <result_reporter class="com.android.tradefed.result.XmlResultReporter" /> </configuration>
Agora, recrie o Tradefed e execute novamente o exemplo do 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 registro informando que um arquivo XML foi gerado. as 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>
Também é possível escrever seus próprios listeners de invocação personalizados. Eles simplesmente é preciso implementar ITestInvocationListener (em inglês) interface gráfica do usuário.
O Tradefed oferece suporte a vários listeners de invocação para que você possa enviar os resultados do teste.
a vários destinos independentes. Para isso, basta especificar vários
Tags <result_reporter>
na sua configuração.
Instalações de geração de registros (D, I, R)
Os recursos de geração de registros do TF incluem a capacidade de:
- Capturar registros do dispositivo (também conhecido como logcat do dispositivo)
- Gravar registros do framework da Trade Federation em execução na máquina host (também conhecido como registro do host)
O framework do TF captura automaticamente o logcat do dispositivo alocado
e a envia ao listener da invocação para processamento.
Em seguida, XmlResultReporter
salva o logcat do dispositivo capturado como um arquivo.
Os registros de host do TF são relatados
Wrapper CLog
para a classe Log ddmlib. Vamos converter
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());
O CLog
processa a interpolação de strings diretamente, de forma semelhante a
String.format
. Ao recriar e executar novamente o TF, você verá a
mensagem de registro na stdout:
tf> run example/helloworld … 05-16 21:30:46 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548 …
Por padrão, negociada
gera registro do host
mensagens para stdout. O TF também inclui uma implementação de registro que grava
mensagens em um arquivo:
FileLogger.
Para adicionar a geração de registros de arquivos, 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, recrie 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 registro indica o caminho do registro do host que, quando visualizado, vai conter a mensagem de registro HelloWorldTest:
more /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt
Exemplo de saída:
… 05-16 21:38:21 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548
Opções de processamento (D, I, R)
Objetos carregados de uma configuração do TF (também conhecida como objetos de configuração)
também podem receber dados de argumentos de linha de comando usando a chamada
@Option
.
Para participar, uma classe de objeto de configuração aplica o @Option
a um campo de membro e fornece a ele um nome exclusivo. Isso permite que
valor do campo de membro a ser preenchido por uma opção de linha de comando (e também
adiciona automaticamente essa opção ao sistema de ajuda de configuração).
Observação:nem todos os tipos de campo são compatíveis. Para um descrição dos tipos compatíveis, consulte OptionSetter (link em inglês).
Adicione um @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";
A seguir, vamos adicionar uma mensagem de registro para exibir o valor da opção HelloWorldTest para que possamos demonstrar que ele foi recebido corretamente:
@Override public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { … CLog.logAndDisplay(LogLevel.INFO, "I received option '%s'", mMyOption);
Por fim, recrie o TF e execute helloworld; vai aparecer uma mensagem de registro
Valor padrão de my_option
:
tf> run example/helloworld … 05-24 18:30:05 I/HelloWorldTest: I received option 'thisisthedefault'
Transmitir valores da linha de comando
Transmita um valor para my_option
. vai aparecer
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
texto de ajuda para os campos @Option
. Experimente agora para ver
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 "como imprimir apenas as opções importantes". Para reduzir
desorganização, o TF usa o atributo Option#importance
para
determina se o texto de ajuda de um campo @Option
específico será mostrado ao
--help
é especificado. --help-all
sempre mostra ajuda para
todos os campos @Option
, independentemente da importância. Para mais detalhes, consulte
Option.Importance.
Transmitir valores de uma configuração
Também é possível especificar um valor de opção na configuração adicionando um
<option name="" value="">
. Faça o teste usando
helloworld.xml
:
<test class="com.android.tradefed.example.HelloWorldTest" > <option name="my_option" value="fromxml" /> </test>
A recompilação e a execução de helloworld agora devem 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 do
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 aceita opções. A opção
--log-level-display
é interessante porque filtra os registros que
vão aparecer na stdout. Mais cedo no tutorial, você deve ter notado que "Hello, TF
Mundo! Eu tenho o dispositivo..." a mensagem de registro parou de ser exibida em stdout depois que
passou a usar FileLogger
. É possível aumentar o nível de detalhes
geração de registros para stdout transmitindo o argumento --log-level-display
.
Tente isso agora. A mensagem "Tenho um dispositivo" vai aparecer a mensagem de registro reaparece em 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ê ficar preso em algo, o Comércio O código-fonte da federação tem muitas informações úteis que não estão expostas na a documentação. Se nada der certo, pergunte no android-platform (link em inglês) Grupo do Google, com "Trade Federation" no assunto da mensagem.