Автор: Антон Сирота (QA, Automation)
В этой статье, основанной на лекции, которую я недавно читал, мы рассмотрим фреймворк Appium. Это вводный материал, предназначенный для понимания, как в принципе происходит автоматизация мобильных приложений, что для этого потребуется, с чего, собственно, начинать работу и с какими сложностями придется столкнуться.
Автоматизация мобильных приложений — относительно новое явление, но его востребованность постоянно растет. Кое-какие трудности есть и с Appium, хотя в целом процесс автоматизации с его использованием уже отлажен.
Содержание
? Окружение для мобильной автоматизации
? Поиск и работа с элементами
? Работа с драйвером
? Работа с контекстами
? Эмулятор или реальное устройство?
? Возможные проблемы/трудности
? Процесс мобильной автоматизации
? Облачные сервисы
Виды мобильных приложений:
? Нативные.
? Веб.
? Гибридные.
Перед тем как говорить об автоматизации, стоит рассмотреть виды самих мобильных приложений.
Нативные приложения. Основной вид мобильных приложений, устанавливаются на телефон и работают непосредственно на телефоне. Нативные приложения не требуют браузера и интернета, а если и требуют, не зависимы от их наличия.
Веб-приложения. Сейчас часто встречаются адаптивные дизайны, которые адаптируют веб-приложение с десктопной версии под мобильную. Тестировать такие приложения нужно в условиях, максимально приближенных к реальной среде, — на эмуляторах или устройствах.
Гибридные приложения. Нативные приложения, внутри которых встроена возможность открывать веб-страницы, когда доступ к вебу реализован через нативное приложение.
Окружение для автоматизации
iOS Automation | Android Automatoin |
---|---|
Maс OS | Mac OS / Windows / Linux |
XCode | Android SDK |
Node Js | Emulator setup |
Appium | Appium |
Application | Application |
Haxm driver (for SDK Emulator) |
Перед тем как начинать процесс автоматизации, важно понять, какое окружение нужно будет настроить. И, естественно, две основные операционные системы, с которыми придется иметь дело, — iOS и Android.
Что для старта требует iOS? Apple — целостная система, поэтому, если завтра нужно будет автоматизировать iOS-приложение, вам нужна будет операционная система Mac, как вариант — разворачивать все можно на Mac-mini. Почему? Потому что нам нужен будет xCode с Mac OS.
Следующим инструментом будет Appium. Есть две возможности запуска Appium: UI или консольная. Для установки и запуска консольной версии нам дополнительно понадобится NodeJs. А UI-версию можно скачать с официального сайта, и она сразу будет готова к работе.
Если мы говорим об автоматизации веб-приложений, нам будет необходимо убедиться, что на эмуляторе установлен браузер. Для Android это будет Google Chrome, для iOS — Safari (который по дефолту всегда уже есть в эмуляторе).
Если тестируем нативное приложение, которое нам дали разработчики, мы должны убедиться, что оно есть на нашей машине, и указать путь — как к нему можно получить доступ в Appium.
Для Android-автоматизации вопрос выбора операционной системы не столь критичен — здесь все можно настроить под Windows, Linux и MacOS. Нужно учесть, что под виртуальной машиной не всегда получается развернуть Android-автоматизацию из-за отсутствия графического адаптера, без которого мы просто не сможем запустить Android-эмулятор. Для старта нам будет нужен Android SDK, т. е. девелопмент-кит для Android, в котором уже есть встроенный эмулятор.
Следующий шаг — настройка эмулятора. Там же можно создать и настроить эмулятор и эмулировать практически любой Android-устройство.
Также нам понадобится Appium и само .apk-приложение, либо Chrome.apk для Android. Важно знать, что у стандартного эмулятора Android существует не большая проблема: SDK — эмулятор очень медленный, чтобы его ускорить, при создании эмулятора можно поставить галочку “Use host GPU”, при этом должен быть установлен Haxm-драйвер (упомянутый в списке). Тогда эмулятор начинает работать с более-менее приличной скоростью. Конечно, есть и более стабильные и быстрые инструменты типа Genymotion — он условно бесплатный, но, если вы захотите использовать его в своем проекте, вам придется приобретать платную лицензию.
Поиск и работа с элементами
Tools:
? Appium Inspector
? UI Automator Viewer (Android)
? UI Automation (iOS)
Locators:
• Xpath
• Id
• Class
• Name
• UI Automation id
• Css (mobile web only)
• Accessibility id (ios only)
Если вы работаете с мобильными веб-приложением, можно просто открыть его в браузере, уменьшить до размера нужного устройства и находить нужные элементы.
Если приложение нативное или гибридное, понадобится Appium Inspector — встроенный инспектор в Appium работает и с Android, и с iOS. Т. е., если у вас запущена UI-версия Appium, вы можете нажать Inspect, после чего появится дерево элементов приложения. Также есть отдельные программы: UI Automator Viewer для Android и UI Automation для iOS. Это вспомогательные инструменты, позволяющими видеть элементы и находить их, чтобы в дальнейшем использовать при автоматизации.
Какие локаторы существуют? Даже для нативных приложений мы можем использовать тот же язык разметки, что и для веб-приложений — Xpath. ID, если у элементов есть любые ID. Можно также использовать Class или Name, есть еще и UI Automation ID — он может пригодиться, если в стандартном дереве не видно какого-то элемента. Т. е., когда элемент есть на устройстве, есть на эмуляторе, мы его видим, но в дереве элементов и в xml его нет — такое тоже бывает. UI Automation позволяет записать ваши действия, сгенерировать после этого код, части которого можно использовать в автоматизации. Можно использовать CSS, но нужно учесть, что CSS-локаторы будут работать только при автоматизации мобильных веб-приложений.
Пример нахождения локаторов в нативных приложениях
Открывая UI Automation Viewer, слева вы увидите скриншот экрана, справа — дерево элементов, которые есть в приложении. Мы можем пойти по дереву и построить Xpath. Локатор будет использовать два слеша и включать элементы, которые позволят построить зависимость.
У нас есть дерево и детали по каждому элементу приложения. Т. е. мы берем какой-то элемент, и можем видеть у него class, index, text, id и т.д. Все это можно использовать при поиске элемента. При построении локатора, мы можем найти элемент по классу, если класс уникальный. Также у нас может присутствовать resource_id, внутри которого есть id=, такие элементы могут находится непосредственно по id=. Appium Inspector будет очень похож на UI Automation viewer, который идет в пакете с Android SDK (папка tools, и в ней uiautomatorviewer.bat файл, который запускает UI Automation viewer и позволяет смотреть дерево элементов). С его помощью можно видеть элементы не только на эмуляторе — вы можете находить те же самые элементы с реального устройства, если он подключен через кабель.
В UI Automation Viewer можно кликнуть на кнопку device screenshot, тогда он подключается к эмулятору с помощью ADB и получает через него скриншот и xml открытого приложения. После получения скриншота и дерева элементов мы можем проверить, есть ли у нас нужные элементы и проверить, по каким атрибутам можно составить уникальный локатор. Таким образом и находятся элементы в нативных приложениях.
Работа с драйвером
WebDriver — RemoteWebDriver – AppiumDriver = IOSDriver / AndroidDriver
Перед тем как работать с драйвером, необходимо настроить среду, эмулятор, установить на эмулятор приложение, открыть и убедиться, что элементы приложения доступны в дереве элементов. То есть проверить, что у вас все готово для дальнейшей автоматизации.
После этого можно строить непосредственно автоматизацию. Также стоит упомянуть прослойки в автоматизации, где конечная точка — ваше приложение, которое установлено на устройстве, уровнем ниже — устройство, с ним и взаимодействует Appium, который устанавливается отдельно. Команды в Appium передаются из кода, который в целом будет выглядеть почти так же, как при автоматизации веб-приложений с использованием Selenium. Т. е. у вас используется тот же Page Object, вы так же работаете с элементами, только это будут уже не WebElements, а MobileElements. Сам код взаимодействует с Appium через драйвер.
Веб-драйвер — интерфейс, в котором имеется каркас возможных действий. Дальше идет RemoteWebDriver, который наследует WebDriver. Дальше — AppiumDriver, который будет необходим при автоматизации мобильных нативных приложений (при автоматизации мобильных веб-приложений можно использовать RemoteWebDriver). И уже от AppiumDriver, наследуются IOSDriver и AndroidDriver, в которых определенные действия реализуются по-своему для каждой операционной системы.
Если подробнее:
? WebDriver — базовый интерфейс.
? RemoteWebDriver — часто используется для автоматизации с применением Selenium Grid (автоматизация веб-приложений).
? AppiumDriver — общий абстрактный класс для автоматизации мобильных приложений.
? IOSDriver — используется для iOS Automation.
? AndroidDriver — используется для Android Automation.
Использовать RemoteWebDriver при автоматизации мобильных веб-приложений не всегда удобно, потому что иногда возникает необходимость обратиться к определенным нативным частям. В том же Facebook, если вы будете автоматизировать мобильную веб-версию приложения, после ввода логина и пароля выскочит предложение запомнить пароль. А после апрува выскочит нативный pop-up, который будет блокировать сайт, пока вы не нажмете “Ok”. Чтобы это сделать, вам уже потребуется AppiumDriver (или iOSDriver/AndroidDriver), который сможет работать с нативным контекстом, т. к. RemoteWebDriver может работать только с веб-контекстами.
AppiumDriver (General abstract class for Mobile) — абстрактный класс для мобильной автоматизации и для автоматизации Android/iOS. В зависимости от устройства, вы можете использовать IOSDriver или AndroidDriver, который наследуется от AppiumDriver.
Пример инициализации
Этот пример взят из реального проекта. Здесь мы можем указать необходимые нам capability. После того как среда для автоматизации готова, можно реализовать все в коде, который дальше и будет отправлять нужные запросы в Appium. Чтобы это сделать, вам нужно указать URL, по которому он будет идти в Appium, и нужные capability.
В примере инициализации показаны настройки для Mobile Chrome и Mobile Safari. В capability обозначено browserName, где мы указываем, будет ли это Chrome или Safari. Далее у нас могут быть использованы разные устройства и платформы. Есть еще autoAcceptAlerts, чтобы не выскакивали нативные аллерты, и newCommandTimeout, который устанавливается, чтобы сообщить драйверу, при каком простое ему завершить сессию.
Работа с контекстами
Получить все контексты:
getDriver().getContextHandles();
Переключить контекст:
getDriver().context("WEBVIEW");
getDriver().context("NATIVE_APP");
getDriver().context("CONTEXT_NAME");
В большей степени это касается гибридных приложений. При автоматизации нативных приложений нам поможет либо Appium Inspector, либо UI Automator Viewer. Что касается гибридных приложений, когда открывается нативное приложение, после определенных шагов можно в этом же приложении открыть веб-страницу, или будет отображаться ее часть.
В этом примере открыт Appium Inspector. Именно так он выглядит, когда открыто IOS-приложение. Дерево элементов здесь открывается последовательно. Вы выбираете какой-либо элемент и, если внутри есть еще элементы, отобразится следующее дерево внутренних элементов. Здесь есть возможность видеть контексты, т. е. вы можете выбрать NATIVE_VIEW — нативный контекст, или WEB_VIEW — веб-контекст.
Бывает и так, что у вас идет нативная шапка в приложении, а ниже следует встроенная веб-страница. В таких случаях у вас есть несколько контекстов, и вы можете переключаться между ними для поиска нужных элементов.
Как это работает? Если говорить, как это реализуется в коде, у вас есть драйвер, в котором есть возможность получить все контексты вызовом метода getContextHandles().
Также у вас есть Appium-инспектор, чтобы подтвердить, что все контексты в наличии; есть возможность вывести из кода все контексты, которые есть на текущий момент, после чего вы можете переключаться на эти контексты.
То есть основное, что вам понадобится — это метод getContextHandles(), который берет все контексты, которые есть на текущей открытой странице приложения.
Если нужно переключиться между контекстами, открываете в тесте нативное приложение, доходите в нем до веб-части, после чего нужно переключиться с нативного контекста на веб. Для этого вызываете метод context(), который есть в AppimDriver, и указываете в нем контекст, на который нужно переключиться — к примеру, WEB_VIEW или NATIVE_VIEW.
Устройства или эмуляторы
Real Device | Emulator | |
---|---|---|
Простота настройки | Android: Быстрая установка iOS: Придется покопаться |
Android: Есть подводные камни при настройке iOS: требует xCode и минимальных настроек |
Скорость прогона | Быстро | Android: скорость зависит от эмулятора iOS: низкая скорость запуска, быстрый прогон |
Стабильность | Относительно стабильно | Android: Есть определенные нестабильности iOS: Проблему можно решить дополнительными bash-скриптами |
Поведение | Может отличаться в зависимости от версии OS | Может отличаться в зависимости от версии OS |
Доступность элементов | В WebView элементы могут определяться, как Native | В WebView элементы доступны, как веб-элементы |
Мы работали и с реальным устройствами, и с эмуляторами. В каждом случае обнаружились плюсы и минусы.
Реальное Android-устройство в целом удается настроить довольно быстро. Нужно убедиться, что на устройстве включен developer mode. А после подключения устройства нужно на самом телефоне подтвердить подключение, нажав на выскочившем окне “Ok”, и все — ценой минимальных усилий вы готовы автоматизировать мобильные приложения на Android.
Если мы имеем дело с iOS, придется покопаться — там при подключении реального устройства свои сложности. Связка с Appium возможна, но нужно потратить время, чтобы ее настроить.
Если говорить об Android-эмуляторе, основной подводный камень — проблема быстродействия. Стандартный эмулятор очень медленный, но установка haxm-драйвера и выбор Use Host GPU при настройке эмулятора позволяют его ускорить.
Если это веб-автоматизация, важно устанавливать правильную версию браузера. Например, если у вас платформа х86, нужно ставить Google Chrome тоже версии х86.
Если рассматривать iOS-эмулятор, в целом все не столь сложно — понадобятся минимальные настройки. Нужно запустить Appium, чтобы на Xcode был эмулятор нужной версии. К примеру, чтобы прогнать тест на iPhone 6, под iOS 9.3, нужно просто убедиться, что именно эта версия присутствует в Xcode.
В целом реальные устройства работают быстрее, чем эмуляторы. В случае с эмуляторами, у Android скорость зависит от самого эмулятора. В качестве альтернативы Android имеется эмулятор Genymotion, который устанавливается довольно быстро и работает шустрее и стабильнее стандартного. Используя Genymotion, можно гонять тесты в несколько потоков на одной машине, что позволяет заметно увеличить скорость прохождения тестов.
Если говорить об IOS-эмуляторе, получаем высокую скорость прогона, но низкую скорость запуска теста. Потому что, если запускаем тест в новой сессии (а чаще всего нам это понадобится, чтобы работать на чистом приложении), он будет каждый раз переоткрывать эмулятор, что отнимает время. При этом сами тесты бегут довольно быстро.
В Android-эмуляторах могут наблюдаться определенные нестабильности. Если говорить о реальных устройствах, все относительно стабильно. Но в целом проблемы с нестабильными прогонами под стандартным эмулятором можно частично решить дополнительными batch-скриптами — они перед стартом тестов будут убивать все лишние процессы (которые могли остаться с предыдущего прогона) и стартовать чистую сессию Appium и эмулятора перед прогоном группы тестов.
Бывают случаи, когда поведение приложения может отличаться в зависимости от версии операционной системы, какие-то всплывающие окна могут не появляться вообще или наоборот выскакивать постоянно. Это мелочи, но такое случается — такие моменты тоже приходится как-то обрабатывать.
Доступность элементов
До сих пор мы заметили такое только в одном проекте: в нативном приложении открывается веб-страница, а элементы на этой странице определяются по-разному на эмуляторе и реальном устройстве. Бывает, что элементы на реальном устройстве определяются как нативные, а в эмуляторе все работает как WebView, т. е. как обычный веб-сайт, где мы можем найти элементы даже по CSS-локатору.
Как я уже отметил, подобную разницу мы заметили в одном проекте: мы могли по CSS-локатору найти элемент, который будет отлично работать на эмуляторе, но, когда запускаем этот же тест на реальных устройствах, он в принципе ничего не находит, даже веб-контекст, — и видит все как нативный контекст.
Возможные проблемы
? Некоторые элементы могут быть недоступны.
? Не все стандартные методы работают правильно (ex. scroll/swipe).
? Нужно следить за обновлениями.
? Нужно следить за соответствием версий (OS, Appium, Emulator).
? Важно правильно настроить эмулятор.
В случае с автоматизацией мобильных приложений все еще не так идеально отлажено, как в веб-автоматизации, но в целом все проблемы, которые мы рассмотрели, решаемы. На это просто придется потратить некоторое время.
Как я упоминал ранее, некоторые элементы могут оказаться недоступны. У нас был случай, когда валидация на странице была визуально видна, но в дереве элементов ее не было. Можно вызвать getPageSource(), как при веб-автоматизации, и нам вернется xml текущей открытой страницы, т. е. все, что видно на странице на данный момент. Но чаще всего, если элемент не доступен в инспекторе, xml тоже ничего нового не откроет. В этом случае есть два варианта решения: либо оставлять этот кейс на ручное тестирование, либо пообщаться с девелоперами, попросить их добавить ID или другие дополнительные атрибуты.
Не все стандартные методы работают правильно. И здесь нужно понимать, что Appium — фреймворк относительно новый, если сравнивать его, скажем, c Selenium. Это заметно, если говорить о таких действиях, как scroll/swipe, когда нам нужно в нативном приложении пролистнуть влево/вправо или вверх/низ. В AppiumDriver есть метод scrollToText(), который может пролистнуть страницу к определенному тексту, но, к сожалению, пока для iOS он не всегда стабильно работает. Будьте готовы, что придется писать свой кастомный scroll — в интернете есть определенные решения, которые можно использовать.
В AppiumDriver есть также метод swipe, но у него очень много параметров. Поэтому чтобы использовать его в тестах, чаще всего нужно будет писать свою обертку, которая будет передвигать экран на определенное количество процентов или пикселей вправо-влево. Т. е. в целом вопрос решаемый, но с проблемой придется столкнуться.
Необходимо следить за обновлениями и соответствием версией — что-то из того, что раньше в Appium не работало, успешно работает в новых версиях. Т. е. нам придется обновлять Appium как Application так же, как API в коде. В обоих случаях мы должны стараться поддерживать самую последнюю версию, потому что ее регулярно улучшают и дорабатывают. При этом, если у вас последняя версия Appium и какой-нибудь старый xCode со старым эмулятором, приложение, возможно, работать не будет.
Mobile Automation Workflow
Собственно, вот так все и должно работать в идеале. Нативное приложение — файл, который нам нужно откуда-то взять, а затем использовать при прогоне тестов. Таким образом, чтобы процесс автоматизации был реализован правильно, нужна сборка, которая соберет мобильное приложение. К примеру, автоматическая сборка Аndroid-приложения, которая создаст .apk-файл. Дальше может по триггеру автоматически запускаться Jenkins задача, которая будет передавать локацию собранного .apk-приложения и прогонять на нем нужные тесты. Можно настроить сборку приложения и прогон на ней тестов каждую ночь, таким образом, тесты у нас всегда будут up-to-date, и мы сможем каждое утро видеть и анализировать результаты прогона тестов и выявлять баги максимально оперативно.
Облачные сервисы
Для автоматизации iOS-тестов нам был необходим Mac-mini. Но что если нам необходимо обеспечить мультипоточность? Допустим, есть 300 тестов, и они в один идут поток 12 часов, а получить результаты нам нужно всего за час. Работать становится куда сложнее: для каждого потока нужна отдельная mac-машина. При этом нужно постоянно следить за обновлениями версий Appium, Xcode и OS.
В облачных сервисах вы платите относительно небольшую сумму за возможность его неограниченного использования и можете выбрать нужное количество потоков. При правильном подходе можно убедить заказчика, что за счет полученных возможностей и экономии времени на поддержку локальных сред тестирования он скорее сэкономит, чем потратит лишнее.
Возьмем BrowserStack. Этот вендор выделяет виртуальные машины, а мы просто указываем в коде RemoteUrl, по которой будут гоняться тесты. И, если мы указали прогон в три потока, это автоматически будет распределяться на три машины на стороне browserstack. К тому же, все приложения они обновляют вовремя и внимательно следят за совместимостью. Значит, работать встанет значительно легче. Самое весомое преимущество облачных сервисов в том, что вы не тратите массу времени на настройку и поддержку окружений для автоматизированного тестирования.
Преимущества облачных сервисов
:• Не тратим время на настройку среды.
• Не тратим время на поддержку среды.
• Стабильная работа.
• Более высокая скорость прохождения тестов (чаще всего).
• Простая реализация мультипоточности.
Облачные сервисы также предоставляют видеозапись того, что происходит — это касается и мобильных, и веб-приложений. А если вам нужно тестировать под определенной системой, к примеру Windows XP или Internet Explorer 8, вы можете с легкостью установить параметры при прогоне теста, а облачный сервис автоматически запустит тест под нужным окружением. Кстати, для мануального тестирования тот же browserstack предоставляет возможность бесплатного пользования.
Теперь можно не тратить время на настройку среды и ее поддержку: просто говорим тесту, на каком окружении ему прогоняться, и всегда знаем, что все последние обновления там уже установлены.
Стабильная работа облачных сервисов означает, что вам не нужно будет писать дополнительные скрипты, которые контролируют стабильность прогона и старт скриптов в чистой сессии. Тесты в облачных сервисах обычно бегут быстрее, хотя, если у вас будет абсолютно топовая и очень дорогая Mac-машина, в скорости можете и выиграть. Но если у вас стоит Mac-mini позапрошлого года, даже с хорошими позапрошлогодними параметрами, тест не будет таким быстрым, как у большинства облачных сервисов.
Тем более, облачный сервис позволяет нам запустить одну задачу в несколько потоков и, соответственно, ваши 9-часовые тесты можно прогнать за час-два.
Поделиться с друзьями
Artem_zin
Поясните плз. Если речь идет о нескольких инстансах Genymotion, то со стандартными эмуляторами тоже можно так делать.
В чем вообще видите профит Appium? Кроме того, что нужно разбираться с одним тулом вместо нескольких. По факту пошарить сами тесты между платформами никогда не получается, работает Appium оооочень медленно. Есть более нормальные решения в виде Espresso для Android и KIF для iOS.
LionAlex
Преимущества в тестировании black box, у нас это был основной критерий при выборе инструмента. Также, работа через wd протокол позволяет писать тесты на любом языке.
Espresso и XCUITest мы используем для более низкоуровневых тестов, а-ля такие функциональные юниты.
Artem_zin
Что вам дает black box? Этого можно добиться путем code review и с instrumentation api (Espresso/etc).
И вы пишете на …?
Cкорость выполнения тестов с Appium критически низкая, как вы с этим боритесь?
LionAlex
Того, что мы не видим и не лезем в код приложений. Вопрос тут скорее политический, но для компании важный.
В основном PHP. Один тестовый проект с одной инфраструктурой под все платформы (api, веб, ios, android) с минимальными изменениями.
Да не сказал бы, что прям критически низкая, у нас сетевые задержки иногда больше. На ios используем instruments-without-delay, чтобы убрать секундную задержку, воткнутую Эпплом.
Artem_zin
То есть вы код тестов держите в отдельном от приложения репозитории? А как тогда синхронизируете? Это же боль…
ооооок, снимаю шляпу!
Это для отдельной дискуссии, TL;TR: не надо лезть на реальный бекенд в тестах :)
LionAlex
Именно. Иногда боль, да, но мы держимся
Ну так исторически сложилось, да
Вряд ли буду согласен на 100%. Все-таки хочется тестировать реальное приложение с api, а не моки. Мокаем только самое необходимое.
Artem_zin
ок, спасибо за дискуссию!