Recursos de inatividade do Espresso

Um recurso de inatividade representa uma operação assíncrona com resultados que afetam operações subsequentes em um teste de interface. Registrando recursos de inatividade com Espresso, é possível validar essas operações assíncronas com mais confiabilidade ao para testar seu app.

Identificar quando os recursos de inatividade são necessários

O Espresso oferece um conjunto sofisticado de recursos de sincronização. Isso característica da estrutura, no entanto, só se aplica a operações que publicam mensagens no MessageQueue, como uma subclasse de View que está desenhando o conteúdo na tela.

Como o Espresso não tem conhecimento de nenhuma outra operação assíncrona, incluindo quando são executados em um thread de segundo plano, o Espresso não consegue oferecer a sincronização garantias nessas situações. Para fazer com que o Espresso reconheça os erros operações de longa duração, é preciso registrar cada uma delas como um recurso de inatividade.

Se você não usar recursos de inatividade ao testar os resultados da trabalho assíncrono, talvez precise usar uma das seguir soluções incorretas para melhorar os testes confiabilidade:

  • Adicionar chamadas a Thread.sleep(). Quando você adicionar atrasos artificiais aos testes, o pacote de testes levará mais tempo para termine a execução, e seus testes ainda podem falhar às vezes quando executados em dispositivos mais lentos. Além disso, esses atrasos não têm bom escalonamento, porque o app pode ter que realizar trabalhos assíncronos mais demorados em uma versão futura.
  • Implementação de wrappers de repetição,que usam um loop para verificar repetidamente se o app ainda está executando trabalho assíncrono até atingir o tempo limite. Mesmo que você especificar uma contagem máxima de novas tentativas em seus testes, cada nova execução consome recursos do sistema, principalmente a CPU.
  • Usando instâncias de CountDownLatch, que permite que uma ou mais linhas de execução aguardem até que um número específico de operações sejam executados em outra linha de execução sejam concluídos. Esses objetos exigem que você especifique um tempo limite Caso contrário, ele poderá ser bloqueado por tempo indeterminado. As travas também adicionam complexidade desnecessária ao código, dificultando a manutenção.

O Espresso permite remover essas soluções alternativas não confiáveis dos testes e registre o trabalho assíncrono do app como recursos de inatividade.

Casos de uso comuns

Ao executar operações semelhantes aos exemplos a seguir nos testes, use um recurso de inatividade:

  • Carregar dados da Internet ou de uma fonte de dados local.
  • Estabelecer conexões com bancos de dados e callbacks.
  • Gerenciar serviços usando um serviço do sistema ou uma instância do IntentService
  • Executar lógica de negócios complexa, como transformações de bitmap.

É muito importante registrar recursos de inatividade quando essas operações atualizar uma interface validada pelos seus testes.

Exemplo de implementação de recursos de inatividade

A lista a seguir descreve vários exemplos de implementações de recursos de inatividade que você pode integrar ao seu app:

CountingIdlingResource
Mantém um contador de tarefas ativas. Quando o contador for zero, o valor é considerado inativo. Essa funcionalidade se assemelha à de um Semaphore: Na maioria dos casos, essa implementação suficientes para gerenciar o trabalho assíncrono do app durante os testes.
UriIdlingResource
Semelhante a CountingIdlingResource, mas o contador precisa ser zero por um período específico antes que o é considerado inativo. Esse período de espera adicional leva solicitações de rede, quando um app na linha de execução pode fazer uma nova imediatamente após receber uma resposta a uma solicitação anterior.
IdlingThreadPoolExecutor
Uma implementação personalizada de ThreadPoolExecutor que monitora o número total de tarefas em execução na linha de execução criada. piscinas Esta classe usa um CountingIdlingResource para manter o contador de tarefas ativas.
IdlingScheduledThreadPoolExecutor
Uma implementação personalizada de ScheduledThreadPoolExecutor. Ele oferece a mesma funcionalidades e recursos IdlingThreadPoolExecutor aula, mas também pode acompanhar tarefas que estão agendadas para o futuro ou estão programados para execução periódica.
.

Criar o próprio recurso de inatividade

À medida que você usa recursos de inatividade nos testes do app, pode ser necessário fornecer e geração de registros ou gerenciamento de recursos personalizados. Nesses casos, as implementações listados na seção anterior podem não ser suficientes. Se esse for o caso, você pode estender uma dessas implementações de recursos de inatividade ou criar o seu próprio;

Se você implementar sua própria funcionalidade de recurso de inatividade, considere as seguintes práticas recomendadas em mente, especialmente a primeira:

Invocar transições para o estado inativo fora das verificações de inatividade
Depois que seu app ficar inativo, chame onTransitionToIdle() fora das implementações isIdleNow() Dessa forma, O Espresso não faz uma segunda verificação desnecessária para determinar se uma determinada recurso inativo está inativo.

O snippet de código a seguir ilustra essa recomendação:

Kotlin

fun isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

fun backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}

Java

public void isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

public void backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}
Registrar recursos de inatividade antes que eles se tornem necessários

Os benefícios da sincronização associados aos recursos de inatividade só entram em vigor após a primeira invocação do Espresso de método isIdleNow().

A lista a seguir mostra vários exemplos dessa propriedade:

  • Se você registrar um recurso de inatividade em um método anotado com @Before, o recurso de inatividade entra em vigor na primeira linha de cada teste.
  • Se você registrar um recurso de inatividade em um teste, entra em vigor durante a próxima ação baseada no Espresso. Esse comportamento ainda ocorre mesmo se a próxima ação estiver no mesmo teste que a instrução que registra o recurso de inatividade.
Cancelar o registro de recursos de inatividade depois de usá-los

Para conservar os recursos do sistema, cancele o registro dos recursos de inatividade assim que possível porque você não precisa mais deles. Por exemplo, se você registrar um recurso de inatividade em um método com a anotação @Before, é melhor cancelar o registro desse recurso em uma método correspondente com a anotação @After.

Usar um registro de inatividade para registrar e cancelar o registro de recursos de inatividade

Ao usar esse contêiner para os recursos de inatividade do app, é possível registrar e cancelar o registro de recursos de inatividade repetidamente conforme necessário e ainda observar do seu modelo.

Manter apenas o estado simples do app nos recursos de inatividade

Por exemplo, os recursos de inatividade que você implementa e registra não devem contêm referências a objetos View.

Registrar recursos de inatividade

O Espresso oferece uma classe de contêiner na qual você pode colocar o estado inativo do app. do Google Cloud. Essa classe, chamada IdlingRegistry é um artefato independente que introduz uma sobrecarga mínima no app. A classe também permite que você realize as seguintes etapas para melhorar a performance do seu app capacidade de manutenção:

  • Criar uma referência ao IdlingRegistry, em vez dos recursos inativos que ele contém nos testes do app.
  • Manter diferenças na coleção de recursos de inatividade que você usa para cada variante de build.
  • Definir recursos de inatividade nos serviços do app, e não na interface que se referem a esses serviços.
.

Integrar recursos de inatividade ao app

É possível adicionar recursos de inatividade a um app de várias maneiras, em particular, mantém o encapsulamento para o app e ainda permite para especificar uma operação específica representada por um determinado recurso de inatividade.

Ao adicionar recursos de inatividade ao app, é altamente recomendável colocar o lógica de recursos de inatividade no próprio app e realizando apenas as tarefas de de cancelamento de registro nos testes.

Embora você crie a situação incomum de usar uma interface somente de teste em código de produção seguindo essa abordagem, é possível unir recursos de inatividade que você já tem, mantendo o tamanho do APK e a contagem de métodos do app.

Abordagens alternativas

Se você preferir não ter a lógica de recursos de inatividade na produção do seu app o código, há várias outras estratégias de integração viáveis:

  • Criar variantes de build, como as produto variações e usam recursos de inatividade somente no build de depuração do app.
  • Use um framework de injeção de dependência como o Dagger (em inglês) para injetar o tempo de inatividade do app. gráfico de dependência de recursos nos testes. Se você estiver usando o Dagger 2, a a própria injeção precisa se originar de um subcomponente.
  • Implementar um recurso de inatividade nos testes do app e expor a parte da implementação do app que precisa ser sincronizada provas.

    Atenção : embora essa decisão de design pareça criar uma referência independente para recursos de inatividade, ela também interrompe em todos os apps, exceto no mais simples.

Outros recursos

Para mais informações sobre o uso do Espresso em testes do Android, consulte o recursos a seguir.

Amostras