Известно, что автотесты упрощают процесс тестирования и избавляют тестировщиков от необходимости вручную проверять значительную часть приложения. Автоматизация тестирования значительно сокращает процесс тестирования и время от начала разработки до выхода продукта на рынок (time-to-market).
В контексте автоматизации тестирования взаимодействие с самим приложением часто осуществляется через шаблон Page Object.
Скачать одну из самых популярных книг по тестированию "Как тестируют в Google"
Page Object — это шаблон, в котором тестируемый экран (независимо от платформы) описывается как набор интерактивных элементов (кнопок, иконок или текстов).
На приведённом выше изображении можно увидеть три интерактивных элемента:
- Стрелка «Вперёд».
- Стрелка «Назад».
- Кнопка «Закрыть».
Также при тестировании элементов экрана можно учитывать заголовок и описание страницы.
Если говорить о разработке под Android, то наиболее известными инструментами для автоматизации тестирования являются Espresso и Appium. Основное отличие заключается в том, что Espresso может тестировать только приложения для Android, в то время как Appium работает как с Android, так и с iOS-приложениями.
Существуют различные способы обнаружения элементов на экране. Самые распространённые — по тексту и по идентификатору ресурса (resource ID). Если тестируется собственное приложение, то довольно легко получить идентификатор ресурса, указанный разработчиком в исходном коде.
@Test fun greeterSaysHello() { onView(withId(R.id.name_field)).perform(typeText("Steve")) onView(withId(R.id.greet_button)).perform(click()) onView(withText("Hello, Steve!")).check(matches(isDisplayed())) }
Однако сейчас взаимодействия пользователя не ограничиваются только одним приложением: возможна интеграция с другим, сторонним приложением, а также появление системных уведомлений от приложения. Часто, если у компании есть несколько продуктов с общим или близким функционалом, они активно рекламируются внутри приложения. Например, Kaspersky Internet Security имеет всплывающий баннер с рекламой приложения WhoCalls, который ведёт на страницу в Google Play.
Давайте рассмотрим следующий тест-кейс:
- Открыть главный экран приложения.
- Нажать на кнопку «Загрузить WhoCalls».
- Убедиться, что открыта страница в Google Play (в заголовке указано WhoCalls).
Опытный тестировщик сразу же заметит различные негативные сценарии. Самый очевидный — когда пользователь не вошёл в учётную запись Google: вместо необходимой страницы приложения в Google Play отобразится следующий экран:
В этом случае пользователь должен войти в систему, введя свой логин и пароль. К тому же, иногда Google Play может попросить пользователя повторно ввести учётные данные из-за подозрительной активности — такие сценарии должны быть включены в состав автотеста. Но как тестировать такие приложения, если нет доступа к исходному коду?
Выбор инструмента для тестирования сторонних приложений. Определение интерактивных элементов
Для тестирования сторонних приложений недостаточно использовать только Espresso, необходимо использовать дополнительный инструмент под названием UI Automator. Стоит также отметить, что работа с Appium может решить эту проблему, так как он использует встроенный UI Automator для платформы Android. Но в отличие от Espresso, использование только Appium ограничивается тестирование методом чёрного ящика. Например, нельзя определить элементы, которые не видны на экране.
UI Automator — это фреймворк для тестирования, который позволяет автоматизировать взаимодействие с пользовательским интерфейсом приложений для Android. Его API позволяет взаимодействовать с видимыми элементами на устройстве.
Таким образом можно взаимодействовать практически с любым приложением, даже не имея доступа к исходному коду.
Способ определения элемента на экране аналогичен Espresso, но с другим синтаксисом. В большинстве случаев элемент можно определить по тексту и идентификатору.
val okButton: UiObject2 = device.findObject( By.text("OK").clazz("android.widget.Button") )
Подробнее о UI Automator и его возможностях можно узнать в документации.
В данном случае со входом через учётную запись Google этот метод сделает тест «хрупким», например в ситуации, когда текст внутри кнопки изменится или локализация на устройстве будет изменена.
Может показаться, что гарантированным способом обнаружения элемента является неизменяемый ID. Но ID часто замаскирован в конфигурационных файлах, поэтому полезно использовать все доступные варианты.
Вот несколько способов определения элемента на экране:
- UI Automator Viewer
- Сторонние приложения (Developer Assistant)
- Dump
Давайте рассмотрим каждый из этих инструментов и разберём их плюсы и минусы.
UI Automator Viewer
UI Automator Viewer — это инструмент для определения иерархии расположения элементов на экране, а также атрибутов самих элементов.
Этот инструмент доступен в Android SDK по умолчанию.
Как видно на изображении, идентификатор элемента замаскирован, поэтому для определения элемента нужно использовать текст или класс представления элемента.
Сторонние приложения (Developer Assistant)
Если по какой-то причине у вас нет доступа к Android SDK, то можно использовать приложение Developer Assistant, которое доступно в Google Play. После настройки приложения вы сможете определять атрибуты элементов на устройстве аналогично UI Automator Viewer.
Плюсом является возможность определения атрибутов элементов непосредственно на устройстве без доступа к Android SDK. Однако Developer Assistant не умеет определять элементы для системных диалогов и уведомлений.
Dump
Вы можете выгружать содержимое экрана в отдельный файл, используя функции UI Automator.
Прежде чем использовать эту команду, необходимо открыть экран, информацию о котором вы хотите получить.
Написание автотеста для приложения из Google Play. Kaspresso и Kautomator
Переходя к реализации автотеста, необходимо выбрать инструмент, на котором будет написан автотест. Из самых популярных можно выделить Espresso и UI Automator.
Вот пример того, как будет выглядеть тест с использованием этих инструментов:
package com.example.kaspressoarticle import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.BySelector import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiObject2 import androidx.test.uiautomator.Until import org.junit.Assert.* import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @LargeTest class GooglePlayPromoTest { @get:Rule val activityRule = ActivityScenarioRule(MainActivity::class.java) @Test fun checkSignInButtonGooglePlay() { // step 1 main screen onView(withText("Download WhoCalls!")).perform(click()) // step 2 check google play we are signed in val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) device.wait(Until.hasObject(signInButtonSelector), TIMEOUT) val signInButton: UiObject2? = device.findObject(signInButtonSelector) assertTrue(signInButton != null) // true if sign in button visible, false otherwise } companion object { private const val TIMEOUT = 3000L private val signInButtonSelector: BySelector = By.text("Sign in") } }
Как видите, для взаимодействия с разными элементами используются разные синтаксисы. Существует популярный фреймворк с открытым исходным кодом — Kaspresso, который позволяет устранить эти различия в синтаксисе и поддерживать единый стиль при написании автотестов. Kaspresso использует Kakao и Kautomator — DSL-оболочки Espresso и UI Automator, предоставляя интуитивно понятный интерфейс.
Рассмотрим пример автотеста, написанного с помощью Kaspresso:
package com.example.kaspressoarticle import io.qameta.allure.kotlin.Allure.step import junit.framework.TestCase import org.junit.Test class GooglePlayPromoKaspresso : TestCase() { @Test fun checkSignInButtonGooglePlay() = run { step("1. Click WhoCallsPromo") { MainScreen { whoCallsPromoButton { click() } } } step("2. Check \"Sign in\" button is visible") { GooglePlayScreen { signInButton { isDisplayed() } } } } }
Как видите, для описания экранов используется шаблон Page Object. Вот код для объектов страниц:
package com.example.kaspressoarticle import com.kaspersky.components.kautomator.component.text.UiButton import com.kaspersky.components.kautomator.screen.UiScreen import com.kaspersky.kaspresso.screens.KScreen import io.github.kakaocup.kakao.text.KButton object MainScreen : KScreen<MainScreen>() { override val layoutId: Int = R.layout.main_screen override val viewClass = MainActivity::class.java val whoCallsPromoButton = KButton { withText("Download WhoCalls!") } } const val GOOGLE_PLAY_PACKAGE = "com.android.vending" object GooglePlayScreen : UiScreen<GooglePlayScreen>() { override val packageName: String = GOOGLE_PLAY_PACKAGE val signInButton = UiButton { withText("Sign in") } }
Класс KScreen
используется для описания элементов с помощью Kakao, а класс UiScreen
— для описания с помощью UI Automator.
Теперь код стал более читабельным и поддерживает единый подход при написании тест-кейсов.
Преимуществом Kautomator является увеличение стабильности благодаря поддержке интерцепторов, а также более быстрое выполнение автотестов.
Kaspresso предлагает ряд преимуществ по сравнению с использованием только Espresso + UI Automator инструментов:
- Поддержка команд ADB
- Декларативные шаги
- Отчёты и журналы для анализа тестов
Подробнее об этом фреймворке можно узнать здесь.
Заключение
Мы рассмотрели, как тестировать стороннее приложения на примере Google Play, познакомились с методами определения ID элементов экрана стороннего приложения и реализовали тест-кейс с помощью Kaspresso и Kautomator.
Перевод статьи «How we tested a Google Play application».