0Pricing
Android Academy · Урок

Тестирование интерфейса с Espresso

Пишите автоматизированные тесты интерфейса с Espresso. Находите представления через onView(), взаимодействуйте с ними через perform(), проверяйте состояние с помощью check() и тестируйте взаимодействия с RecyclerView.

«Тестирование интерфейса с Espresso» — бесплатный урок Android Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 4 уроков всего.

Что такое Espresso?

Espresso — официальный фреймворк Android для тестирования интерфейса. Он позволяет писать тесты, которые взаимодействуют с интерфейсом приложения: нажимают кнопки, вводят текст, прокручивают списки — и проверяют отображаемое на экране.

Espresso выполняется на устройстве или эмуляторе (инструментальный тест) и автоматически синхронизируется с потоком интерфейса — вызовы sleep() с ненадёжными задержками не нужны.

Настройка

Espresso входит в набор инструментов тестирования Android. Добавьте эти зависимости в app/build.gradle:

// app/build.gradle:
android {
    defaultConfig {
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1'  // RecyclerView
}

ActivityScenarioRule

Используйте ActivityScenarioRule, чтобы запускать Activity перед каждым тестом и закрывать её после:

@RunWith(AndroidJUnit4::class)
class LoginActivityTest {

    @get:Rule
    val activityRule = ActivityScenarioRule(LoginActivity::class.java)

    @Test
    fun `login button is displayed`() {
        onView(withId(R.id.btnLogin))
            .check(matches(isDisplayed()))
    }
}

onView() и ViewMatchers

onView(matcher) находит представление в текущей иерархии. Для точности объединяйте сопоставители:

// Match by ID:
onView(withId(R.id.tvTitle))

// Match by text:
onView(withText("Submit"))

// Match by content description (for accessibility):
onView(withContentDescription("Close dialog"))

// Combine matchers:
onView(allOf(withId(R.id.btnSave), isEnabled()))

// Inside a specific parent:
onView(withId(R.id.btnSave)).inRoot(isDialog())

ViewActions — взаимодействие с представлениями

Найдя представление, выполните действие с помощью .perform():

// Tap a button:
onView(withId(R.id.btnLogin)).perform(click())

// Type into an EditText:
onView(withId(R.id.etEmail))
    .perform(typeText("alice@example.com"), closeSoftKeyboard())

// Clear text and retype:
onView(withId(R.id.etPassword))
    .perform(clearText(), typeText("secret123"), closeSoftKeyboard())

// Scroll to a view:
onView(withId(R.id.btnSubmit)).perform(scrollTo(), click())

// Long press:
onView(withId(R.id.ivImage)).perform(longClick())

ViewAssertions — проверка состояния

Проверьте отображаемое на экране с помощью .check():

// View is displayed:
onView(withId(R.id.tvError)).check(matches(isDisplayed()))

// View has specific text:
onView(withId(R.id.tvTitle)).check(matches(withText("Welcome!")))

// View is not displayed (GONE or INVISIBLE):
onView(withId(R.id.progressBar)).check(matches(not(isDisplayed())))

// View is enabled:
onView(withId(R.id.btnSave)).check(matches(isEnabled()))

// View does not exist:
onView(withId(R.id.tvError)).check(doesNotExist())

Полный тест входа

Полный тест, который вводит учётные данные и нажимает кнопку входа:

@Test
fun `successful login shows home screen`() {
    // Type email
    onView(withId(R.id.etEmail))
        .perform(typeText("alice@example.com"), closeSoftKeyboard())

    // Type password
    onView(withId(R.id.etPassword))
        .perform(typeText("password123"), closeSoftKeyboard())

    // Tap login button
    onView(withId(R.id.btnLogin)).perform(click())

    // Assert welcome message is shown
    onView(withId(R.id.tvWelcome))
        .check(matches(withText("Welcome, Alice!")))
}

Тестирование RecyclerView

Используйте RecyclerViewActions из espresso-contrib, чтобы взаимодействовать с элементами списка:

import androidx.test.espresso.contrib.RecyclerViewActions

@Test
fun `clicking item opens detail screen`() {
    // Scroll to position 5 and click:
    onView(withId(R.id.recyclerView))
        .perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
            5, click()
        ))

    // Assert detail screen is shown:
    onView(withId(R.id.tvDetailTitle)).check(matches(isDisplayed()))
}

Тестирование проверки ввода

Проверьте, что при недопустимом вводе появляются сообщения об ошибке:

@Test
fun `empty email shows error message`() {
    // Leave email blank, tap login
    onView(withId(R.id.btnLogin)).perform(click())

    // Assert error is shown
    onView(withId(R.id.tilEmail))
        .check(matches(hasDescendant(withText("Email is required"))))
}

@Test
fun `short password shows error`() {
    onView(withId(R.id.etPassword))
        .perform(typeText("123"), closeSoftKeyboard())
    onView(withId(R.id.btnLogin)).perform(click())
    onView(withId(R.id.tilPassword))
        .check(matches(hasDescendant(withText("Minimum 6 characters"))))
}

Ресурсы ожидания

Espresso автоматически ждёт освобождения потока интерфейса, но не ждёт завершения сетевых вызовов или сопрограмм. Используйте IdlingResource, чтобы сообщить Espresso, что нужно дождаться асинхронной работы:

// CountingIdlingResource: increment before async work, decrement when done
val idlingResource = CountingIdlingResource("NetworkCall")

// In your ViewModel/Repository:
idlingResource.increment()
viewModelScope.launch {
    loadData()
    idlingResource.decrement()
}

// In test setUp:
@Before
fun setUp() {
    IdlingRegistry.getInstance().register(idlingResource)
}

@After
fun tearDown() {
    IdlingRegistry.getInstance().unregister(idlingResource)
}

Запуск тестов Espresso

Запускайте инструментальные тесты на подключённом устройстве или эмуляторе:

  • В Android Studio: щёлкните тестовый класс правой кнопкой мыши → «Запустить»
  • В терминале: ./gradlew connectedAndroidTest
  • Результаты появятся в app/build/reports/androidTests/

Используйте эмулятор Android с API 28+ для стабильного и быстрого выполнения тестов. Отключите анимации в настройках разработчика, чтобы предотвратить нестабильность.

Быстрая проверка

Каков правильный шаблон Espresso для поиска представления и проверки его текста?

Итоги: тестирование интерфейса с Espresso

Автоматизированное тестирование интерфейса обнаруживает регрессии раньше пользователей:

  • onView(matcher) — найти представление
  • .perform(action) — нажать, ввести текст, прокрутить
  • .check(matches(...)) — проверить видимость, текст и состояние
  • RecyclerViewActions — для взаимодействия со списками
  • IdlingResource — для асинхронных операций
  • Отключайте системные анимации, чтобы предотвратить нестабильность тестов

Далее: отладка и профилирование приложения на профессиональном уровне.

Часто задаваемые вопросы

Урок «Тестирование интерфейса с Espresso» бесплатный?

Да — полный текст урока «Тестирование интерфейса с Espresso» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 4 уроков всего.

Чему я научусь в уроке «Тестирование интерфейса с Espresso»?

Пишите автоматизированные тесты интерфейса с Espresso. Находите представления через onView(), взаимодействуйте с ними через perform(), проверяйте состояние с помощью check() и тестируйте взаимодейств… Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Android Academy?

Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Тестирование интерфейса с Espresso»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Android Academy?

Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Модульное тестирование с JUnit
  2. Имитация объектов с Mockito
  3. Тестирование интерфейса с Espresso
  4. Отладка и профилирование
← Назад к Android Academy