Всем привет!
Меня зовут Сергей Дударев, я руководитель направления автоматизированных тестов в департаменте мобильной разработки «Лаборатории Касперского». В этой статье хочу рассказать, как я прошел путь от Appium до open-source-фреймворка Kaspresso, с чего начинал, какие делал для себя открытия, как разрушались мои стереотипы и какие по итогу были сделаны выводы.
Как пришел к выбору Appium
Когда я перешел в мобильное тестирование, передо мной встал выбор инструмента для автоматизации. Выбирал я между нативными инструментами (Espresso, Kaspresso) и Appium.
На тот момент про Kaspresso было мало информации, из того, что попадалось на просторах Интернета, — это README.md на github и несколько статей, в которых не было достаточно информации, чтобы понять все его возможности.
Из вариантов у меня остались Espresso и Appium.
Последний был более популярен среди моих коллег из соседних команд.
Пообщавшись с ними по поводу их выбора и изучив несколько сравнительных статей Appium с Espresso, я выделил для себя следующие преимущества в пользу Appium:
Appium предполагает меньший порог вхождения по сравнению с нативными инструментами. Получается, что ручным тестировщикам без опыта в написании кода будет проще написать свой первый тест, который начнет приносить пользу, — а значит, интерес к автоматизации будет расти. Я не раз встречал ручных тестировщиков, которые теряли такой интерес, потому что не могли разобраться в сложном проекте и написать свой первый тест. Также я встречал тех, кто начинал писать автотесты в проектах с продуманной архитектурой, составляя свои первые тесты как конструктор из готовых шагов, — интерес у них только нарастал, и они все больше углублялись в автоматизацию, доходя до уровня автоматизатора тестирования. Поэтому чем меньше порог вхождения, тем лучше.
С помощью Appium можно взаимодействовать со сторонними приложениями. В Espresso, например, такой возможности нет. У Android для этого есть отдельный инструмент UIAutomator, но хотелось иметь схожий api по работе как со своим приложением, так и со сторонним. Конкретно это преимущество было ключевым для меня, поскольку специфика проекта подразумевает множество взаимодействий со сторонними приложениями, да и с самой системой Аndroid.
С помощью Appium можно написать один тест для двух платформ сразу (Android и iOS), в отличие от нативных инструментов. Тоже значимый аргумент в пользу appium, ведь выглядит так, будто мы можем решить две задачи одним инструментом.
Так мой выбор пал на стек из python + pytest + appium.
Время экспериментов
На протяжении примерно полугода я автоматизировал тесты, используя этот стек, и вроде бы все шло хорошо, но у меня все больше проявлялся интерес к Kasprеsso — о нем стало появляться все больше информации и лестных отзывов, а также появился туториал, который пошагово объяснял возможности фреймворка.
На тот момент у меня не было понимания, насколько он подходит именно мне, поскольку у проекта есть своя специфика. Я решил написать несколько тестов на Kasprеsso, так сказать, факультативно, без ущерба для автоматизации своего проекта.
Как разрушались мои стереотипы
Взяв у коллег ссылку на туториал по Kaspresso, я начал с ним знакомство, параллельно внедряя фреймворк в свой проект. Оказалось, что это совсем не сложно! Достаточно добавить несколько зависимостей и создать пакет с тестами. Об этом подробно написано в секции интеграции.
Написать первый тест оказалось тоже совсем несложно благодаря понятному и лаконичному Kotlin DSL. Если посмотреть на код теста, становится сразу понятно, что на экране WizardAgreements нажимаем кнопку «Далее», а затем на экране запроса разрешения проверяем, что видна эта кнопка:
@Test
fun requiredPermissionTest() =
run {
step("Agreement Screen") {
WizardAgreementsScreen {
continueButton {
click()
}
}
}
step("Required permission screen") {
RequiredPermissionScreen {
continueButton {
isVisible()
}
}
}
}
Когда я написал первый тест, был разрушен мой первый стереотип про порог вхождения. Долгое время я был уверен: чтобы написать нативный тест, нужно погрузиться в kotlin (c которым я практически не был знаком), глубоко понимать структуру тестируемого приложения. На самом же деле начать писать автотесты на Kaspresso не сложнее, чем на Appium, а как по мне — так и вовсе проще. Убедиться в этом вы сможете сами, пройдя уроки в туториал по Kaspresso.
Когда дело дошло до взаимодействия со сторонними приложениями, разрушился мой второй стереотип. Я считал, что нативные инструменты не подходят для этих задач, но, как оказалось, это правдиво только для Espresso. Если мы хотим тестировать с его помощью, то для взаимодействия с другими приложениями стоит взять другой фреймворк — UIAutomator. Однако Kaspresso создан на основе этих двух инструментов и предоставляет удобные и функциональные обертки над ними. Таким образом, вам не нужно использовать что-либо еще — этот фреймворк закрывает все потребности. Кроме того, мы получаем единый стиль в наших тестах при взаимодействии как со своим приложением, так и со сторонними.
В Appium также используется UIAutomator как один из вариантов взаимодействия с приложениями.
Не менее дискуссионной остается и возможность написать один тест для iOS и Android с помощью Appium. С одной стороны, это действительно так: можно написать один тест на одном языке, который будет запускаться на двух платформах, но по факту два приложения зачастую имеют разный UX и UI (ввиду не только неконсистентности дизайна, но и различий в OS) и различные локаторы для элементов. В итоге вместо единого кода для двух платформ мы получаем много if-ов в коде теста для разделения логики по платформам, из-за чего тест будет громоздким и неудобным в отладке.
Думаю, не стоит ограничиваться одним языком программирования для решения разных задач. Лучше использовать тот язык, который подходит для отдельно взятого кейса, а не тот, который мы лучше знаем. В этом утверждении могут быть исключения (например, эксперименты, которые нужно провести в сжатые сроки), но глобально суть остается прежней.
Дальше — больше
Чем дальше я углублялся в изучение возможностей Kaspresso, тем больше проникался симпатией к нему. Первое, что приходит в голову, — продуманная архитектура тестов. Она основывается на паттерне page object. При написании тестов не нужно продумывать основу их архитектуры, достаточно следовать концепции, заложенной в Kaspresso. Следующее — Kaspresso из коробки предоставляет то, что в своем проекте с Appium мне приходилось придумывать и реализовывать самому. Например:
1. adb
Для взаимодействия с adb-сервером в проекте с Appium мне приходилось писать свою реализацию, которая выполняет adb-команды через python‑библиотеку subprocess. В Kaspresso же достаточно обратиться к интерфейсу adbServer, вызвать метод performShell, который выполняет команды shell в adb (не нужно писать команду целиком, достаточно написать все, что идет после shell), передать в метод команду, которую мы хотим выполнить:
adbServer.performShell("pm list packages")
В ответ получим результат выполнения этой команды.
Еще у adbServer есть методы performAdb, который выполняет команды adb (туда передаем все, что в команде идет после adb), и performCmd — выполняет команды командной строки на хосте, с которого были запущены тесты.
В Espresso же вовсе нет возможности взаимодействовать с adb.
2. Обертки adb-команд
Готовые обертки adb-команд экономят время на поиски того, как эти самые команды составлять. Более того, они избавляют от необходимости реализовывать выполняющие эти adb-команды методы у себя в проекте. Например, чтобы отключить Интернет на устройстве, достаточно вызвать:
device.network.disable()
Нет необходимости знать и выполнять отдельно команды «adb shell svc wifi disable» и «adb shell svc data disable». Также класс Devices имеет большой набор методов для взаимодействия с OS Android: например, можно эмулировать входящие звонки и СМС, устанавливать и удалять приложения, изменять язык. Со всеми другими возможностями класса Devices можно ознакомиться здесь.
3. Автоскролл
В Kaspresso реализован скролл до элемента, с которым мы собираемся взаимодействовать. Этот механизм позволяет не задумываться о том, что на некоторых экранах элемент может не уместиться и быть за его границами. В случае необходимости Kaspresso сам проскроллит до нужного элемента. Это делает тесты стабильнее и ускоряет их написание, ведь теперь нет необходимости реализовывать метод скролла у себя в проекте — а затем еще отдельно продумывать, где добавить его вызов, прежде чем кликать по нему, например.
4. Работа с пермишенами
Есть несколько способов выдачи разрешений, которые поддерживает Kaspresso. Первый — автоматический, при установке приложения, второй — при использовании пользовательского сценария, через UI. Здесь стоит остановиться на втором варианте. В случае с Appium, если у нас стоит задача проверить запрос и применение пермишена, нам нужно найти подходящий для него локатор и написать метод, который будет искать и принимать его на странице.
В случае с Kaspresso нам достаточно вызвать уже реализованный метод, который проверит наличие диалога и пример пермишена при его наличии:
device.permissions.apply {
flakySafely {
Assert.assertTrue(isDialogVisible())
allowViaDialog()
}
}
5. Скриншоты
Наше приложение должно поддерживать множество локализаций, поэтому есть важная потребность просматривать, как выглядят экраны приложения на разных языках. Для решения этой задачи, а также для проведения design review Kaspresso предоставляет очередное готовое решение из коробки. Только посмотрите, как мало нужно написать кода, чтобы снять скриншоты с экрана приложения на 12 языках и сохранить их в папке sdcard/Documents/screenshots/:
WizardAgreementsScreen {
continueButton {
isVisible()
captureScreenshot("AgreementScreen")
}
}
Снимать скриншоты с экрана можно с помощью двух вариантов. Первый – проходя весь пользовательский сценарий вплоть до нужного экрана. Второй -- когда мы не запускаем всё приложение, а стартуем только отдельные фрагменты – это позволяет делать скриншоты быстро и стабильно. Подробно об этом можно почитать здесь. Помимо самих скриншотов, будут сохранены xml файлы с указанием всех строк на экране и их id.
6. Работа с logcat
Есть тесты, в которых недостаточно взаимодействия с UI, ведь часть логики может быть спрятана от пользователя, и для проверки того, что наше приложение отрабатывает так, как мы от него ожидаем, нам нужно обращаться к логам через logcat. Kaspresso и здесь предоставляет нам готовое решение — чтобы найти интересующую строку в логе, достаточно сделать:
device.logcat.readLogcatRows(includePattern = "some string")
7. Steps
Каspresso позволяет делать автотесты более читаемыми благодаря выделению кусков кода в отдельные блоки, которые соответствуют тест-кейсам, а еще добавляет логирование и скриншоты в тесты. Подробнее о steps можно почитать здесь.
8. Защита от флаков
Выше я уже упоминал про автоскролл, но это еще не всё, что предоставляет Kaspresso для повышения стабильности тестов: например, он умеет закрывать системные окна, дожидаться загрузки асинхронных элементов, и это можно легко и гибко настраивать самостоятельно.
Все это экономит многие часы на поиски и реализацию необходимой функциональности. И для этого мне приходилось изобретать свои «велосипеды», а ведь то же время можно было потратить на написание новых автотестов.
Также хотелось бы немного поговорить о, возможно, неочевидном преимуществе нативных инструментов — тесты находятся в одном проекте с тестируемым приложением. Это расширяет наши возможности, позволяя тестировать приложение как white box, что добавляет стабильности тестам и расширяет возможности.
Получается, что Kaspresso…
это фреймворк, с помощью которого каждый желающий сможет начать писать автотесты для Android-приложений, так как порог вхождения у него совсем невысокий. Мои стереотипы относительно нативных инструментов автоматизации были разрушены, ведь большинство из них относились к Espresso. Kaspresso может закрыть все потребности в тестировании Android-приложений.
Если Kaspresso сравнивать с Appium, то в своих возможностях он мало того что не уступает Appium, так еще и во многом превосходит его! Поэтому если вы тоже хотите пробовать новые инструменты и разрушать стереотипы о тестировании и не только — присоединяйтесь к «Лаборатории Касперского»! А чтобы больше узнать о работе с Kaspresso, скорее вступайте в наш чат поддержки. Это большое сообщество c более чем тысячью участников, где есть вся самая полезная информация по работе с фреймворком.