Esta página descreve como escrever um novo executor de testes no Tradefed.
Contexto
Se você quiser saber mais sobre o lugar dos executores de teste na arquitetura do Tradefed, consulte Estrutura de um executor de teste.
Isso não é um pré-requisito para escrever um novo executor de testes. Os executores de testes podem ser escritos isoladamente.
Mínimo necessário: implementar a interface
O mínimo necessário para se qualificar como um executor de testes do Tradefed é implementar a
interface IRemoteTest
e, mais especificamente, o método run(TestInformation testInfo, ITestInvocationListener listener)
.
Esse método é invocado pelo conector quando se usa o executor de testes, semelhante a um Java Runnable.
Cada parte desse método é considerada parte da execução do executor de testes.
Informar resultados do executor de testes
O método run
na interface básica dá acesso a um objeto listener do tipo ITestInvocationListener
. Esse objeto é a chave para informar resultados estruturados do executor de testes para o harness.
Ao informar 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 foram aprovados, reprovados ou em outros estados individualmente.
- Informe as métricas associadas aos testes, se aplicável, por exemplo, métricas de tempo de instalação.
- Se encaixam na maioria das ferramentas de infraestrutura, por exemplo, resultados e métricas de exibição etc.
- Geralmente é mais fácil depurar, já que há um rastreamento mais granular da execução.
No entanto, a geração de relatórios de resultados estruturados é opcional. Um executor de testes pode simplesmente querer avaliar o estado de toda a execução como APROVADO ou REPROVADO, sem detalhes da execução real.
Os seguintes eventos podem ser chamados no listener para notificar o arnês do progresso atual das execuções:
- testRunStarted: notifica o início de um grupo de casos de teste relacionados.
- testStarted: notifica o 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 mudança de estado é considerado aprovado.
- testEnded: notifica o fim do caso de teste.
- testRunFailed: notifica que o status geral da execução do grupo de casos de teste é uma falha. Uma execução de teste pode ser aprovada ou reprovada independente dos resultados dos casos de teste, dependendo do que a execução esperava. Por exemplo, um binário que executa vários casos de teste pode informar todos os casos de teste aprovados, mas com um código de saída de erro (por qualquer motivo: arquivos vazados etc.).
- testRunEnded: notifica o fim do grupo de casos de teste.
Manter e garantir a ordem correta dos callbacks é responsabilidade do implementador do executor de testes. 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.
Você vai notar que essa estrutura de eventos é inspirada na estrutura típica do JUnit. Isso é proposital para manter as coisas próximas de algo básico que os desenvolvedores geralmente conhecem.
Informar registros do executor de testes
Se você estiver escrevendo sua própria classe ou executor de teste do Tradefed, implemente
IRemoteTest
e receba 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 criadores de testes que querem passar para a próxima etapa de teste de dispositivo precisam das seguintes interfaces:
- A IDeviceTest
permite receber o objeto
ITestDevice
que representa o dispositivo em teste e fornece a API para interagir com ele. - O 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 se interessam por essas interfaces para receber artefatos relacionados à execução, por exemplo, arquivos extras, e receber o dispositivo em teste que será segmentado durante a execução.
Testar com vários dispositivos
O Tradefed permite executar testes em vários dispositivos ao mesmo tempo. Isso é útil ao testar componentes que exigem uma interação externa, como um pareamento de smartphone e relógio.
Para gravar um executor de testes que possa usar vários dispositivos, é necessário
implementar a
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 é chamado antes do método run
. Portanto, é seguro presumir que a estrutura estará disponível quando run
for chamado.
Testes que conhecem as configurações
Algumas implementações de executores 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 isso, um executor de teste pode acessar o objeto IConfiguration
de que faz parte e em que é executado. Consulte a descrição do objeto de configuração para mais detalhes.
Para a implementação do executor de testes, 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 do JUnit pode executar individualmente cada teste de unidade.
Isso permite que o conector e a infraestrutura maiores aproveitem esse controle refinado e que os usuários executem parcialmente o executor de testes usando a 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 ele corresponder a um ou mais filtros de inclusão E não corresponder a nenhum filtro 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.