Esta página descreve como escrever um novo test runner no Tradefed.
Contexto
Se você quiser saber mais sobre o lugar dos executores de testes na arquitetura do Tradefed, consulte Estrutura de um executor de testes.
Isso não é um pré-requisito para criar um novo executor de testes. Eles podem ser programados isoladamente.
Mínimo: implementar a interface
O mínimo para se qualificar como executor de testes do Tradefed é implementar a
interface IRemoteTest
e, mais especificamente, o método run(TestInformation testInfo, ITestInvocationListener listener)
.
Esse método é o invocado pelo harness ao usar o test runner, semelhante a um Runnable Java.
Cada parte desse método é considerada parte da execução do gerenciador de testes.
Relatar resultados do executor de teste
O método run
na interface base dá acesso a um objeto de listener do
tipo ITestInvocationListener
. Esse objeto é a chave para informar resultados estruturados
do executor de testes para o harness.
Ao relatar resultados estruturados, um executor de testes tem as seguintes propriedades:
- Informe uma lista adequada de todos os testes executados, quanto tempo eles levaram e se eles foram aprovados, reprovados ou tiveram algum outro estado.
- Informe as métricas associadas aos testes, se aplicável, por exemplo, métricas no momento da instalação.
- Se encaixa na maioria das ferramentas de infraestrutura, por exemplo, métricas e resultados de exibição.
- Geralmente, mais fácil de depurar, porque há um rastro mais granular da execução.
No entanto, o relatório de resultados estruturados é opcional. Um executor de teste pode simplesmente avaliar o estado de toda a execução como APROVADO ou REPROVADO sem nenhum detalhe da execução real.
Os eventos a seguir podem ser chamados no listener para notificar o harness sobre o progresso atual das execuções:
- testRunStarted: notifica o início de um grupo de casos de teste relacionados.
- testStarted: notifica o início do início de um caso de teste.
- testFailed/testIgnored: notifica a mudança de estado do caso de teste em andamento. Um caso de teste sem nenhuma mudança de estado é considerado aprovado.
- testEnded: notifica o fim do caso de teste.
- testRunFailed: notifica que o status geral do grupo de execução de casos de teste é uma falha. Uma execução de teste pode ser aprovada ou reprovada, independentemente dos resultados dos casos de teste, dependendo do que a execução estava esperando. Por exemplo, um binário que executa vários casos de teste pode informar todos os casos de teste pass, mas com um código de saída de erro (por qualquer motivo: vazamento de arquivos etc.).
- testRunEnded: notifica o fim do grupo de casos de teste.
Manter e garantir a ordem adequada dos callbacks é responsabilidade do implementador do test runner. Por exemplo, garantir que
testRunEnded
seja chamado em caso de exceção usando uma cláusula finally
.
Os callbacks de casos de teste (testStarted
, testEnded
etc.) são opcionais. Uma execução
de teste pode ocorrer sem casos de teste.
Essa estrutura de eventos é inspirada na estrutura típica do JUnit. Isso é proposital para manter as coisas próximas a algo básico que os desenvolvedores geralmente conhecem.
Registros de relatórios do executor de testes
Se você estiver escrevendo sua própria classe ou executor de teste Tradefed, vai implementar
IRemoteTest
e receber um ITestInvocationListener
pelo método run()
. Esse listener
pode ser usado para registrar arquivos da seguinte maneira:
listener.testLog(String dataName, LogDataType type_of_data, InputStreamSource data);
Testar com um dispositivo
A interface mínima acima permite executar testes muito simples que são isolados e não exigem recursos específicos, por exemplo, testes de unidade Java.
Os autores de testes que quiserem passar para a próxima etapa do teste de dispositivo vão precisar das seguintes interfaces:
- IDeviceTest
permite receber o objeto
ITestDevice
que representa o dispositivo em teste e fornece a API para interagir com ele. - IBuildReceiver
permite que o teste receba o objeto
IBuildInfo
criado na etapa do provedor de build que contém todas as informações e artefatos relacionados à configuração do teste.
Os executores de teste geralmente têm interesse nessas interfaces para receber artefatos relacionados à execução, por exemplo, arquivos extras, e receber o dispositivo em teste que será direcionado durante a execução.
Testar com vários dispositivos
O Tradefed oferece suporte à execução de testes em vários dispositivos ao mesmo tempo. Isso é útil ao testar componentes que exigem uma interação externa, como um emparelhamento de smartphone e relógio.
Para escrever um executor de teste que possa usar vários dispositivos, você precisa
implementar o
IMultiDeviceTest,
que permite receber um mapa de ITestDevice
para IBuildInfo
que contém
a lista completa de representações de dispositivos e as informações de build associadas.
O setter da interface sempre será chamado antes do método run
. Portanto, é seguro presumir que a estrutura estará disponível quando run
for chamado.
Testes cientes das configurações
Algumas implementações de executor de teste podem precisar de informações sobre a configuração geral
para funcionar corretamente, por exemplo, alguns metadados sobre a invocação ou
qual target_preparer
foi executado antes, etc.
Para fazer isso, um executor de teste pode acessar o objeto IConfiguration
do qual ele faz parte e em que é executado. Consulte a descrição do
objeto de configuração
para mais detalhes.
Para a implementação do test runner, você precisa implementar o
IConfigurationReceiver
para receber o objeto IConfiguration
.
Executor de testes flexível
Os executores de testes podem oferecer uma maneira flexível de executar os testes se tiverem um controle granular sobre eles. Por exemplo, um executor de testes JUnit pode executar individualmente cada teste de unidade.
Isso permite que o harness e a infraestrutura maiores aproveitem esse controle preciso e que os usuários executem parcialmente o executor de teste por meio da filtragem.
O suporte à filtragem é descrito na
interface ITestFilterReceiver,
que permite receber conjuntos de filtros include
e exclude
para os testes
que devem ou não ser executados.
Nossa convenção é que um teste será executado se corresponder a um ou mais dos filtros de inclusão E não corresponder a nenhum dos filtros de exclusão. Se nenhum filtro de inclusão for fornecido, todos os testes serão executados, desde que não correspondam a nenhum dos filtros de exclusão.