Appium и Calabash — одни из самых популярных фреймворков для автоматизации тестирования Android-приложений. У каждого, конечно, есть свои преимущества и недостатки. Их основные ограничения:
Calabash: может управлять только пользовательским интерфейсом, который является частью тестового приложения, в частности, нет поддержки тестирования уведомлений;
- Appium: не может вызывать backdoor-методы в приложениях наподобие Calabash (эти методы очень полезны для настройки состояния тестируемого приложения).
Мы в Badoo пользовались Calabash для автоматизации тестирования, когда Appium только начинал развиваться. Это очень стабильный инструмент, и он до сих пор работает быстрее Appium, так что мы не собираемся мигрировать. Но чтобы автоматизировать такое многофункциональное приложение, как Badoo, нам пришлось обойти ограничение Calabash на работу только с интерфейсом тестового приложения.
Когда-то мы пришли к такому решению. И хотя оно ещё работает, его надёжность снижается из-за множества вариаций устройств с разной диагональю, разными версиями Android и так далее.
В этой статье я расскажу, как мы решили возникшую проблему с помощью добавления в Calabash поддержки UIAutomator2. Если вы слишком нетерпеливы, то скажу по секрету, что в конце есть ссылка на готовый к использованию Ruby Gem.
Осознание проблемы
Давайте посмотрим на высокоуровневую архитектуру Calabash-Android:
Calabash-Android-Server использует фреймворк Robotium, который в свою очередь для управления приложением использует Android-фреймворк Instrumentation. Instrumentation даёт Robotium (а следовательно, и Calabash) доступ к среде исполнения, что позволяет тому управлять интерфейсом приложения и осуществлять вызов методов извне.
Но это также означает, что Robotium может управлять лишь пользовательским интерфейсом, являющимся частью кода приложения. В Appium нет такого ограничения, поскольку он использует UIAutomator.
Решение проблемы
Фреймворк Google Instrumentation является частью вспомогательной Android-библиотеки для тестирования. Он работает в контексте приложения, показывает все взаимодействия системы с приложением и, значит, может управлять ими. На базе Instrumentation построены такие популярные фреймворки для тестирования, как Robotium и Espresso.
Кроме того, Robotium используется в серверной части Calabash-Android и поэтому имеет доступ к информации Instrumentation. Также частью Instrumentation в своё время стал UIAutomator 2.0, что даёт возможность его использования внутри сервера Calabash-Android.
С помощью CalabashInstrumentationTestRunner Ruby-клиент Calabash запускает Instrumentation через ADB. В сервере Calabash CalabashInstrumentationTestRunner является расширением Android-класса Instrumentation. Это объект Instrumentation, передаваемый в Robotium Solo. Благодаря UIAutomator 2, он может быть использован для создания нового объекта UIDevice, который способен управлять всем устройством.
Вот как я пришёл к решению проблемы:
1) Добавил библиотеку UIAutomator в сервер Calabash-Android
Я клонировал проект Сalabash-Android-Server и добавил JAR uiautomator2 в папку lib.
2) Инстанцировал объект UIDevice
В файле InstrumentationBackend.java
я создал метод для инстанцирования объекта UIDevice из UIAutomator.
public static UiDevice getUiDevice() {
if (instrumentation.getUiAutomation() == null) {
throw new NullPointerException("uiAutomation==null: did you forget to set '-w' flag for 'am instrument'?");
}
if(uiDevice == null) {
uiDevice = UiDevice.getInstance(instrumentation);
}
return uiDevice;
}
3) Добавил новую команду с помощью API UIAutomator2
Совсем несложно добавить в Calabash-Android-Server новую команду. Все команды, которые вы используете в коде Ruby, мапятся в интерфейс Actions:
sh.calaba.instrumentationbackend.actions
Давайте реализуем действие для открытия панели уведомлений:
public class PullNotification implements Action {
@Override
public Result execute(String... args) {
InstrumentationBackend.getUiDevice().openNotification();
return new Result(true);
}
@Override
public String key() {
return "pull_notification";
}
}
В этом примере метод key() использован для наименования команды, которая будет использоваться Ruby-клиентом Calabash. При вызове этой команды клиентом она запускает метод execute().
4) Запустил измерение (Instrumentation) с флагом -w
Клонировал Ruby-клиент из https://github.com/calabash/calabash-android. Пропатчил lib/calabash-android/operations.rb
и добавил флаг -w в запуск измерения с использованием команды ADB. Как это сделать, можно посмотреть в этом коммите.
Вышеописанные примеры можно посмотреть в моём форке:
Работающий пример:
Давайте посмотрим, как можно вытянуть панель уведомлений и открыть одно из них.
Клонируйте оба репозитория из вышеупомянутого форка в каталог того же уровня.
git clone
https://github.com/rajdeepv/calabash-android
git clone
https://github.com/rajdeepv/calabash-android-server
В обоих репозиториях переключитесь на ветку
‘uiautomator’
.
Перейдите в папку ruby-gem в репозитории calabash-android и соберите Ruby Gem с помощью команды
bundle exec rake build
.
Включите этот Gem в свой проект.
Измените
start_test_server_in_background
наstart_test_server_in_background(with_uiautomator: true)
.
Команда вытягивания панели уведомлений:
perform_action('pull_notification')
.
- Чтобы «коснуться» нотификации с известным фрагментом текста, используйте
perform_action('uiautomator_touch_partial_text', ‘my partial text')
Готовый к использованию Ruby Gem:
Если не хотите всё это делать, можете скачать готовый gem и просто следовать трём последним пунктам.
Заключение
Мне потребовалось приложить некоторые усилия, чтобы углубиться в код Calabash-Android-Server, понять, как он работает, и исследовать возможность решения проблемы. С первой попытки это сделать не удалось, но в процессе работы я узнал некоторые секреты Instrumentation. Когда-нибудь я ими поделюсь с вами.
Хотя этот пример посвящён автоматизации push-уведомлений с помощью Calabash, тот же подход можно применить к любой задаче, с которой вы столкнётесь в автоматизационных фреймворках на базе Calabash:
тестирование виджетов вашего приложения для домашнего экрана;
обработка намерений (Intent) с помощью диалоговых блоков Complete action using в Android-приложениях;
- тестирование взаимодействия со сторонними приложениями, запущенными из вашего приложения.
Надеюсь, этот пост поможет вам в тестировании ситуаций, выходящих за рамки работы с интерфейсом вашего приложения, с помощью Calabash. Если у вас есть вопросы или любая другая обратная связь — добро пожаловать в комментарии.
Leshrac
Как вы с calabash решаете проблему одновременного запуска тестов на нескольких девайсах (Selenium Grid для appium)?
bayandin
Сейчас мы используем badoo/parallel_cucumber для параллельного запуска cucumber-тестов (не только с calabash). Можете взглянуть на rajdeepv/parallel_calabash им мы пользовались ранее, а идеи по параллелизации calabash-тестов у этих инструментов одинаковые.