Controlar quando um teste de automação termina - Espresso
-
21-12-2019 - |
Pergunta
Tenho uma situação incomum que estou testando.Estou usando o Espresso para escrever meus testes.Eu sei que o Espresso e o InstrumentationTestCase não foram feitos para fazer isso.
Tenho um Listener que criei em uma de minhas aulas que me notificará sobre uma alteração de um determinado valor.Eu uso o ouvinte em meu conjunto de testes.
Quando obtenho o valor do ouvinte, preciso afirmar que o valor foi alterado como tal.
Meu problema é que o teste terminará antes de eu receber o valor do ouvinte.
private void sendSpeedChanges() {
setStaticSpeed(new Random().nextInt(10) + 2);
try {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
consoleActivity.onSpeedChanged(getStaticSpeed(), false);
}
});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
private void createSpeedDelegate() {
EspressoMachineValues.setOnSpeedChangeListener(new EspressoMachineValues.OnSpeedChangeListener() {
@Override
public void onSpeedChanged(double speed) {
//assert speed is correct.
assertTrue(getStaticSpeed() == speed);
}
});
}
Esses são os dois métodos que estou usando.O createSpeedDelegate()
é chamado logo no início.Então eu ligo sendSpeedChanges
.Preciso fazer isso X vezes.
OBSERVAÇÃO:
- Demora cerca de 200 milissegundos para recuperar informações (em média).
- Eu não posso ligar
sendSpeedChanges()
até eu verificar o valoronSpeedChange()
- não posso usar
Thread.sleep();
porque o ouvinte está no thread principal.
eu tentei adicionando um getInstrumentation().wait(2000);
e também getInstrumentation().waitForIdleSync();
Obviamente, nenhum dos dois funciona.
Em um mundo perfeito, eu faria isso:
for (int i = 0; i < 42; i++) {
sendSpeedChanges();
i++;
}
Porém, isso não esperará que o valor seja verificado.E se eu esperar pelo valor, o executor de testes pensa que todos os testes foram concluídos e encerra.
Minha pergunta é, haveria uma maneira de controlar quando o teste for encerrado?Mesmo que meus testes aparecer para ser feito.
Solução
Em seu teste, você precisará criar uma instrução de controle que mantenha o teste em execução pelo tempo que você desejar.
while(myTestNeedsToRun) {
if(speedChangeReceived) {
sendSpeedChange();
speedChangeReceived = false;
}
}
private void createSpeedDelegate() {
EspressoMachineValues.setOnSpeedChangeListener(new EspressoMachineValues.OnSpeedChangeListener() {
@Override
public void onSpeedChanged(double speed) {
//assert speed is correct.
assertTrue(getStaticSpeed() == speed);
speedChangedReceived = true;
}
});
Depois de decidir que terminou de executar o teste, basta definir myTestNeedsToRun = false
e então seu teste terminará.
Outras dicas
Alternativamente, você poderia criar um IdlingResource para monitorar sua velocidade.IdlingResource é a maneira que o Espresso usa para verificar se o thread principal está ocioso ou se não há AsyncTasks em execução no pool AsyncTask.
Dê uma olhada coutingIdlingResource classe no código-fonte da biblioteca.Você poderia implementar algo semelhante a isso.No seu caso, poderia ser algo assim:
[...]
private int mTargetSpeed;
private volatile ResourceCallback resourceCallback;
@Override
public boolean isIdleNow() {
boolean isIdle = false;
if (getStaticSpeed() == mTargetSpeed) {
isIdle = true;
resourceCallback.onTransitionToIdle();
} else {
isIdle = false;
}
return isIdle;
}
Nos seus testes, sempre que quiser esperar a velocidade atingir o nível desejado, você deve fazer:
[...]
SpeedIdlingResource speedIdlingResource = new SpeedIdlingResource ("my_idling_resource");
Espresso.registerIdlingResources(speedIdlingResource);
Dessa forma, o Espresso será bloqueado até que seu recurso ocioso informe ao framework que seu SpeedMonitor está ocioso.Isso é bom porque você aproveita toda a estrutura de sincronização do Espresso para monitorar quando atingiu a velocidade desejada, para que seus testes sejam mais confiáveis e rápidos do que fazer uma espera ocupada.