O Espresso-Intents é uma extensão do Espresso, que permite validar e criar stubs de intents enviadas pelo app em teste. É parecido com o Mockito, mas para intents do Android.
Se o app delegar funcionalidades a outros apps ou à plataforma, você pode usar o Espresso-Intents para se concentrar na lógica do próprio app, supondo que outros apps ou a plataforma funcionem corretamente. Com o Espresso-Intents, é possível combinar e validar intents de saída ou fornecer respostas de stub em vez de respostas de intent reais.
Incluir o Espresso-Intents no projeto
No arquivo app/build.gradle
do seu app, adicione a seguinte linha dentro de
dependencies
:
Groovy
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.6.1'
Kotlin
androidTestImplementation('androidx.test.espresso:espresso-intents:3.6.1')
O Espresso-Intents é compatível apenas com o Espresso 2.1 e versões mais recentes e com a versão 0.3 ou mais recente das bibliotecas de teste do Android. Portanto, atualize essas linhas também:
Groovy
androidTestImplementation 'androidx.test:runner:1.6.1' androidTestImplementation 'androidx.test:rules:1.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
Kotlin
androidTestImplementation('androidx.test:runner:1.6.1') androidTestImplementation('androidx.test:rules:1.6.1') androidTestImplementation('androidx.test.espresso:espresso-core:3.6.1')
Programar regras de teste
Antes de programar um teste do Espresso-Intents, configure uma IntentsTestRule
. Essa é uma
extensão da classe ActivityTestRule
que facilita o uso de
APIs do Espresso-Intents em testes funcionais da interface. Uma IntentsTestRule
inicializa
o Espresso-Intents antes de cada teste anotado com @Test
e libera
Espresso-Intents após cada execução de teste.
O snippet de código a seguir é um exemplo de um IntentsTestRule
.
Kotlin
@get:Rule val intentsTestRule = IntentsTestRule(MyActivity::class.java)
Java
@Rule public IntentsTestRule<MyActivity> intentsTestRule = new IntentsTestRule<>(MyActivity.class);
Correspondência
O Espresso-Intents permite interceptar intents de saída com base em determinados critérios de correspondência, que são definidos usando matchers do Hamcrest. O Hamcrest permite:
- Usar um matcher de intent já existente: opção mais fácil, que quase sempre é preferível.
- implementar o próprio matcher de intent: opção mais flexível. Mais detalhes estão disponíveis na seção "Como escrever matchers personalizados" no Tutorial do Hamcrest.
O Espresso-Intents oferece os métodos intended()
e intending()
para validação e
stubs de intents, respectivamente. Ambos usam um objeto Matcher<Intent>
do Hamcrest como
argumento.
O snippet de código a seguir mostra a validação de intents que usam matchers de intent existentes que correspondem a uma intent de saída que inicia um navegador:
Kotlin
assertThat(intent).hasAction(Intent.ACTION_VIEW) assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE) assertThat(intent).hasData(Uri.parse("www.google.com")) assertThat(intent).extras().containsKey("key1") assertThat(intent).extras().string("key1").isEqualTo("value1") assertThat(intent).extras().containsKey("key2") assertThat(intent).extras().string("key2").isEqualTo("value2")
Java
assertThat(intent).hasAction(Intent.ACTION_VIEW); assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE); assertThat(intent).hasData(Uri.parse("www.google.com")); assertThat(intent).extras().containsKey("key1"); assertThat(intent).extras().string("key1").isEqualTo("value1"); assertThat(intent).extras().containsKey("key2"); assertThat(intent).extras().string("key2").isEqualTo("value2");
Validar intents
O Espresso-Intents registra todas as intents que tentam iniciar atividades no
app em teste. Usando o método intended()
, que é semelhante a
Mockito.verify()
, você pode declarar que uma determinada intent foi vista. No entanto,
o Espresso-Intents não cria stubs de respostas para intents, a menos que você o configure explicitamente
para fazer isso.
O snippet de código abaixo é um exemplo de teste que valida, mas não cria stubs de respostas para uma intent de saída que inicia uma atividade externa "phone":
Kotlin
@Test fun validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)) // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")) }
Java
@Test public void validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)); // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")); }
Criar stubs
Usando o método intending()
, que é semelhante a Mockito.when()
, é possível
fornecer uma resposta de stub para atividades iniciadas com
startActivityForResult()
. Isso é particularmente útil para atividades externas,
porque não é possível manipular a interface do usuário de uma atividade externa nem
controlar o ActivityResult
retornado para a atividade em teste.
Os snippets de código abaixo implementam um exemplo de teste
activityResult_DisplaysContactsPhoneNumber()
, que verifica se, quando um
usuário inicia uma atividade de "contato" no app em teste, o número de telefone
de contato é mostrado:
Crie o resultado a ser retornado quando uma atividade específica for iniciada. O teste de exemplo intercepta todas as intents enviadas para "contatos" e apaga as respostas com um
ActivityResult
válido, usando o código de resultadoRESULT_OK
.Kotlin
val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)
Java
Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData);
Instrua o Espresso a fornecer o objeto de resultado de stub em resposta a todas as invocações da intent "contacts":
Kotlin
intending(toPackage("com.android.contacts")).respondWith(result)
Java
intending(toPackage("com.android.contacts")).respondWith(result);
Verifique se a ação usada para iniciar a atividade produz o resultado de stub esperado. Nesse caso, o teste de exemplo verifica se o número de telefone "123-345-6789" é retornado e exibido quando a "atividade de contatos" é iniciada:
Kotlin
onView(withId(R.id.pickButton)).perform(click()) onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)))
Java
onView(withId(R.id.pickButton)).perform(click()); onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)));
Este é o teste activityResult_DisplaysContactsPhoneNumber()
completo:
Kotlin
@Test fun activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData) // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result) // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()) // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))) }
Java
@Test public void activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData); // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result); // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()); // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))); }
Outros recursos
Para saber mais sobre o uso do Espresso-Intents em testes do Android, consulte os recursos a seguir.
Exemplos
- IntentsBasicSample:
uso básico de
intended()
eintending()
. - IntentsAdvancedSample: simula um usuário buscando um bitmap usando a câmera.