Espresso

Espresso-Intents to rozszerzenie Espresso, które umożliwia weryfikację i skrócenie zamiarów wysyłanych przez testowaną aplikację. Podobnie jak Mockito, tylko dla intencji Androida.

Jeśli Twoja aplikacja przekazuje funkcje innym aplikacjom lub platformie, możesz użyć Espresso-Intents, aby skupić się na swojej logice, zakładając, że inne aplikacje lub platforma będą działać prawidłowo. Dzięki Espresso-Intents możesz dopasowywać i weryfikować wychodzące intencje, a nawet podawać pełne odpowiedzi zamiast rzeczywistych intencji.

Uwzględnij intencje espresso w swoim projekcie

W pliku app/build.gradle aplikacji dodaj ten wiersz w obrębie pliku dependencies:

Odlotowy

androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0'

Kotlin

androidTestImplementation('androidx.test.espresso:espresso-intents:3.4.0')

Espresso-Intents jest zgodne tylko z Espresso 2.1+ i bibliotekami testowymi na Androida w wersji 0.3 lub nowszej, dlatego pamiętaj o zaktualizowaniu tych wierszy:

Odlotowy

androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

Kotlin

androidTestImplementation('androidx.test:runner:1.4.0')
androidTestImplementation('androidx.test:rules:1.4.0')
androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0')

Pisanie reguł testowych

Przed utworzeniem testu Espresso-Intents skonfiguruj IntentsTestRule. Jest to rozszerzenie klasy ActivityTestRule, które ułatwia użycie interfejsów Espresso-Intents API w testach funkcjonalnego interfejsu użytkownika. IntentsTestRule inicjuje intencje Espresso przed każdym testem z adnotacją @Test i udostępnia je po każdym przeprowadzeniu testu.

Ten fragment kodu jest przykładem IntentsTestRule:

Kotlin

@get:Rule
val intentsTestRule = IntentsTestRule(MyActivity::class.java)

Java

@Rule
public IntentsTestRule<MyActivity> intentsTestRule =
    new IntentsTestRule<>(MyActivity.class);

Dopasowanie

Espresso-Intents umożliwia przechwytywanie intencji wychodzących na podstawie pewnych kryteriów dopasowania, które są określane przy użyciu funkcji Hamcrest Matchers. Hamcrest umożliwia:

  • Użyj istniejącego mechanizmu dopasowywania intencji: najprostsza opcja, która powinna być prawie zawsze preferowana.
  • Zaimplementuj własne dopasowanie intencji: najbardziej elastyczna opcja. Więcej informacji znajdziesz w sekcji „Pisanie niestandardowych dopasowań” w samouczku Hamcrest.

Espresso-Intents udostępnia metody intended() i intending() odpowiednio do weryfikacji intencji i skrócenia kodu. Oba używają obiektu Hamcrest Matcher<Intent> jako argumentu.

Ten fragment kodu pokazuje weryfikację intencji, która wykorzystuje istniejące dopasowania intencji pasujące do intencji wychodzącej, która uruchamia przeglądarkę:

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");

Zweryfikuj intencje

Espresso-Intents rejestruje wszystkie intencje, które próbują uruchomić działania w testowanej aplikacji. Za pomocą metody intended(), która jest podobna do Mockito.verify(), możesz potwierdzić, że dana intencja została zaobserwowana. Jednak espresso-Intents nie powiela odpowiedzi na intencje, chyba że dokładnie to skonfigurujesz.

Ten fragment kodu to przykładowy test, który sprawdza poprawność odpowiedzi, ale nie ukrywa odpowiedzi na wyjściową intencję, która uruchamia zewnętrzne działanie „telefon”:

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"));
}

Szlifowanie

Za pomocą metody intending(), która jest podobna do Mockito.when(), możesz podać wycinek odpowiedzi w przypadku działań uruchamianych za pomocą startActivityForResult(). Jest to szczególnie przydatne w przypadku działań zewnętrznych, ponieważ nie można manipulować interfejsem użytkownika zewnętrznego działania ani kontrolować funkcji ActivityResult zwracanej do testowanej aktywności.

Te fragmenty kodu implementują przykładowy test activityResult_DisplaysContactsPhoneNumber(), który sprawdza, czy po uruchomieniu przez użytkownika aktywności związanej z kontaktem w testowanej aplikacji wyświetla się kontaktowy numer telefonu:

  1. Utwórz wynik zwracany po uruchomieniu określonego działania. W tym przykładzie test przechwytuje wszystkie intencje wysyłane do „kontaktów” i ukrywa ich odpowiedzi za pomocą prawidłowego atrybutu ActivityResult przy użyciu kodu wyniku RESULT_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);
    
  2. Poproś Espresso, by w odpowiedzi na wszystkie wywołania intencji „kontakty” udostępnia obiekt wyniku wycinka kodu:

    Kotlin

    intending(toPackage("com.android.contacts")).respondWith(result)
    

    Java

    intending(toPackage("com.android.contacts")).respondWith(result);
    
  3. Sprawdź, czy działanie użyte do uruchomienia aktywności przynosi oczekiwany wynik. W tym przypadku test pokazuje, czy numer telefonu „123-345-6789” jest zwracany i wyświetlany po uruchomieniu „aktywności związanej z kontaktami”:

    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)));
    

Oto pełny test activityResult_DisplaysContactsPhoneNumber():

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)));
}

Dodatkowe materiały

Więcej informacji o używaniu Espresso-Intents w testach Androida znajdziesz w tych materiałach.

Próbki