26 апреля 2024
Блог
Автоматизация UI-тестирования на мобильных платформах
Рассказываем про плюсы и минусы UI-тестирования мобильных приложений.
Что такое UI Тестирование Мобильных приложений.
Когда мы говорим о тестировании в True Engineering, то можем сказать, что добиваемся стабильно высокого качества продукта различными инструментами и подходами. В организации и настройки QA процессов мы не прошли мимо пирамиды тестирования.
В основании такой пирамиды лежат unit-тесты. Если говорить простым языком, то это тесты, проверяющие функционал модулей (зачастую просто классов) и не зависят ни от чего более. На втором уровне располагаются интеграционные тесты, которые могут ответить на вопрос, правильно ли работают готовые модули в рамках архитектуры системы. А в самой вершине находятся E2E (end-to-end) тесты. В отличие от основания пирамиды, где тестируются отдельные части системы, E2E – это тесты, которые взаимодействуют с системой через внешние интерфейсы.
В случае мобильного приложения такими тестами является UI-тесты. Вот об этом кусочке тестирования именно мобильных решений мы и расскажем в этой статье.
UI-тесты приложения - это специальным образом написанные программные тестовые сценарии, выполняющиеся на реальном устройстве и симулирующие взаимодействие пользователя с приложением. Попросту говоря – это сценарии, которые проходит пользователь при использовании веб-решения или мобильного приложения. Сценарии могут быть позитивными, когда пользователь дошел до нужного результата, и негативные, когда у него не получилось по каким-то причинам, и приложение должно корректно отработать эту ситуацию. А мы как разработчики должны убедиться, что все отработало как надо.
То есть UI-тесты – это именно те тесты, которые проверяют не только логику работы приложения, но также отвечают на вопрос, корректно ли отображение пользовательского интерфейса с точки зрения пользователя.
Плюсы и минусы
Как у всего в нашей жизни, в применении в проектах UI-тестов для мобильных приложений есть свои положительные и отрицательные моменты. И важно чётко понимать, какие задачи мы решаем с помощью написания тестов, какой результат мы получаем и какие готовы выделять на это ресурсы.
Итак, плюсы, т.е. что дает проекту применение автоматизированных UI-тестов:
- Позволяют автоматически проверить основную функциональность приложения.
- Позволяют выявлять ошибки не только в логике, но и в поведении приложения.
- Закрывают часть регрессионного тестирования. Т.е. за счет автоматизации снижают стоимость и увеличивают скорость регресса. Казалась бы – ну уменьшили регресс, меньше придется QA специалисту тыкать, в чем выгода? Но! Во-первых, автоматизация уменьшает показатель time-to-market и позволяет чаще и быстрее выводить версии продукта на рынок. А во-вторых, когда продукт уже большой и многофункциональный, позволяет не увеличивать количество QA-специалистов, что является уже постоянными и несокращаемыми, по сути, издержками в проекте (не проверять же мы приложение не можем, так ведь?)
- Повышают уровень покрытия проекта регулярными автоматическими проверками. А покрытие – это снижение рисков и гарантированное покрытием качество продукта.
Но есть и некоторые минусы:
- Ресурсные затраты на создание и поддержку выше, чем у интеграционных и unit-тестов. И сильно выше, чем «один раз проверить вручную» (не даром они на вершине пирамиды). Именно поэтому имеет смысл автоматизировать проверку UI-тестами «стабильной» функциональности. А новые фичи и функциональность проверять в ручном режиме до тех пор, пока функциональность не станет стабильной и, по сути, не будет включена в ядро продукта или приложения.
- UI-тесты требуют времени и ресурса для поддержки в актуальном состоянии. Как ни крути, но даже интерфейсы стабильной функциональности дорабатываются, обновляются визуально, анализируется обратная связь от пользователей и вносятся улучшения
- Имеют ограничение, так как привязаны к элементам пользовательского интерфейса и могут «делать выводы» только на основе изменений в нём.
При некоторых минусах и ограничениях UI-тесты имеют минимум три стратегических плюса, особенно когда продукт становится большой и многофункциональный:
- Они позволяют быстро проверить и гарантировать работоспособность всей критичной функциональности
- Сделать это управляемо и без кратного увеличения команды тестирования
- Провести проверку гарантированно «быстро», т.е. оставаясь в целевых сроках. Иногда это может быть автоматическая проверка «ночной сборки», иногда регресс перед релизом или смоук-тестирование выпущенной сборки на промышленном окружении.
На круг это позволяет сделать ваше продукт на рынке более конкурентным – гибким и быстрым к изменениям.
С теорией более-менее разобрались. Давайте заглянем под капот, чтобы понимать, что это из себя представляет для мобильных приложений на iOS и на Android.
Как мы тестируем мобильные проекты в True Engineering
Тестирование мобильных приложений – процесс иной, часто более сложный, чем тестирование web-приложений. При тестировании мобильных приложений необходимо учитывать, что приложение может быть запущено на разных версиях устройства и мобильной ОС, и при этом вести себя по-разному. Также в отличие от web-приложения, мобильное взаимодействует с некоторыми встроенными функциями смартфона – биометрия, камера, датчики. Дополнительными этапами проверки может быть тестирование приложения в условиях отсутствия стабильного интернет-соединения, севшей батарейки и режим энергосбережения и т.д.
Для своих мобильных проектов мы используем как раз ежедневное UI-тестирование. Это позволяет убедиться, что мы ничего не сломали в уже существующей функциональности и вылавливать проблемы на ранних стадиях – по сути во время разработки. В тесте мы задаем целевое поведение пользователей и прогоняем критичные позитивные пути. Именно в этом же цель приложения – пользователь должен быть в состоянии сделать то, для чего оно предназначено.
Android
Для тестирования Android приложений мы используем «нативный» стек. Тесты пишем на Kotlin с помощью библиотеки Kaspresso. Данная библиотека содержит набор классов для удобного взаимодействия с элементами интерфейса, существенно упрощая написание сценария теста. С помощью этого же фреймворка собираются артефакты запуска теста, которые могут содержать как текстовый лог сценария, так и скриншоты ключевых точек прохождения теста, ошибочных ситуаций. Т.е. после прогона теста мы видим всё, что нужно для анализа.
Код теста выглядит вот так:
{
step("1. Авторизация") {
scenario(
AuthorizeScenario(auth = TestData.auth)
)
}
step("2. Перейти в профиль и открыть паспорт") {
HomeScreen.avatar.click()
ProfileDetailsScreen.editProfileButton.click()
EditProfileScreen.editPassportDataClick()
}
step("3. Установить фокус на поле \"Серия и номер\"") {
EditPassportScreen.seriesNumberFieldInput.click()
}
step("4. Нажать на плашку \"Сканировать документ\"") {
EditPassportScreen.scanDocumentButton.click()
}
step("5. Отсканировать файл из вложения") {
step("Выбрать фото из галереи") {
CameraScreen.fromGalleryButton.click()
StartFragmentScreen {
pickPhotoButton.isVisible()
idle(1_000)
pickPhotoButton.click()
}
SelectFileScreen {
clicksToPhoto()
photoClick(TestData.file.resName)
}
}
}
step("Поля паспорта заполнились содержимым из отсканированного паспорта ${TestData.file.resFullName}") {
EditPassportScreen {
seriesNumberFieldInput.isVisible()
compareValue(seriesNumberFieldInput, TestData.passportData.seriesNumber)
compareValue(startDateFieldInput, TestData.passportData.issueDate)
compareValue(issuerCodeFieldInput, TestData.passportData.issuerCode)
compareValue(issuedByFieldInput, TestData.passportData.issuerBy)
compareValue(birthDateFieldInput, TestData.passportData.birthDate)
}
}
}
В этом тесте мы выполнили несколько простых и стандартных для приложения шагов:
- Открыли приложение
- Авторизовались
- Зашли в профиль и встали на поле заполнения паспорта
- Вместо внесения руками нажали на управляющий элемент “сканировать документ”
- Дополнительно проверили возможность загрузить фото паспорта из галереи. Часто ведь нет паспорта под рукой, но есть его фото.
- Убедились, что распознавание прошло успешно и поля формы заполнились.
Profit!
iOS
В продуктах для этой платформы используются средства Xcode, т.е “нативные” уже для платформы от Apple. Xcode предоставляет нам фреймворк XCTest, который мы используем для написания как unit, так и UI тестов. XCTest использует API специальных возможностей (Accessibility API) для доступа к элементам управления в вашей иерархии представлений и взаимодействия с ними. По сути, это средства разработки приложения, которые сделали удобными и для разработчиков тестов.
Код для проверки приложения для iPhone выглядит так:
func testCheckForClaimRolledVision() {
feature("Отображение списка заявок (сокращенный/развернутый вид)")
let checkCellsForSwitchChanges = { [weak self] in
func cellID(for switchValue: Bool) -> String {
return switchValue ? InspectionUIElements.cellShort.rawValue : InspectionUIElements.cell.rawValue
}
guard let self else { return }
turnClaimSwitch(isOn: true)
app.tables.first.cells.toArray.forEach { XCTAssert($0.identifier == cellID(for: true)) }
turnClaimSwitch(isOn: false)
app.tables.first.cells.toArray.forEach { XCTAssert($0.identifier == cellID(for: false)) }
turnClaimSwitch(isOn: true)
}
step("Заявок 3 и меньше") {
showClaimsScreen(for: .user8)
XCTAssert(app.tables.first.cells.count < 3)
XCTAssert(!isClaimSwitchON)
}
step("Щелкнуть на тумблер \"Отобразить карточки списком\"") {
checkCellsForSwitchChanges()
}
back()
openMainTab()
logout()
step("Заявок более 3") {
showClaimsScreen(for: .user9)
XCTAssert(app.tables.first.cells.count >= 3)
XCTAssert(isClaimSwitchON)
}
step("Щелкнуть на тумблер \"Отобразить карточки списком\"") {
checkCellsForSwitchChanges()
}
}
В этом тесте мы протестировали экран со списком заявок и различными представлениями этого списка.
Прекрасно, тесты есть, мы их можем запускать сами или вставить в конвейер CI/CD. Но вот как обработать результатов десятков, а чаще сотней тестов?
Визуализация и обработка результатов
Для визуализации результатов на обоих платформах мы используем фреймворк Allure. Это специальный и довольно мощный open-source инструмент, нацеленный как на обработку и визуализацию результатов тестирования. Он предоставляет как сводную, общую информацию, так и может обогащать результаты тестов дополнительной информацией для анализа – логи, шаги тестов, временные метки (тайминги) и т.д. И плюс он интегрируется с конвейерами сборки и доставки (CI/CD) и трекинговыми платформами. А это значит, что он аккуратно вписывается в производственную инфраструктуру нашей компании и, при желании, компании заказчика.
Отчет о прохождении теста выглядит вот так:
Платформа бесплатная и развивается сообществом.
Главная ценность для нас – это то, что автоматизированные тесты не существуют в проекте и в продуктах ради моды или крутизны. Они аккуратно вписаны в процессы и инструменты нашей фабрики производства и приносят понятную, измеримую и ощутимую пользу именно бизнес-заказчикам в первую очередь. Они ускоряют выпуск приложений в промышленное окружение, а мобильные приложения - в магазины приложений.
Заключение
Работа над качеством продукта начинается с проработки концепции продукта и плана внедрения MVP и не заканчивается никогда. У нас в компании есть объединенный отдел тестирования и сопровождения. Это позволяет нам анализировать ошибки и найденные баги на всех стадиях производства продукта и его последующего промышленного сопровождения.
Сегодня мы рассказали только о небольшом кусочке комплексного процесса обеспечения качества продуктов, которые мы создаем. Часто автотесты преподносятся как «модный и современный» инструмент. Мы с этим не спорим. Но, как и всё остальное, что мы используем в нашей работе, автотесты нацелены в первую очередь на получение качественного бизнес-результата в виде веб-решения или приложения и быстрому выводу этого решения на рынок.
В следующих статьях планируем рассказать о тестировании требований, тестировании данных, о методах функционального и нефункционального тестирования, решениях для быстрого тестирования мобильных приложений, о Quality Gates в рамках конвейера, проверке информационной безопасности и многом другом. Заглядывайте к нам на сайт почаще, у нас уже много интересного, а в планах - еще больше.