Компания
486,79
рейтинг
25 июня 2014 в 16:05

Разработка → Тестирование в Яндексе. Что мы узнали о фреймворке Appium, и можно ли его применять для серьёзных задач

В мире тестирования программного обеспечения набирает обороты совсем молодое направление — автоматизация тестирования мобильных приложений. И ожидаемо, что как грибы после дождя стали появляться соответствующие инструменты: Calabash, iOS Driver, Robotium, Selendroid, Appium. И именно про наши эксперименты с последним в мобильном тестировании я и хочу рассказать.

В последнее время Appium часто упоминают на конференциях и тут, на Хабре, было уже несколько постов о нем. Это фреймворк с открытыми исходным кодом, написанный на JavaScript и предназначенный для автоматизации тестирования мобильных приложений. По сути, это Selenium WebDriver, но для мобильных приложений. Appium позволяет управлять Safari и Chrome на соответствующих устройствах, а значит, и тестировать под ними веб-сайты, но обзор этих возможностей и нюансов, связанных с ними, — отдельная тема.

Чтобы уберечь вас от тех шишек, которые мы сами набили, работая с Appium, я хочу рассказать вам о том, с какими особенностями фреймворка мы столкнулись, какие у вас могут возникнуть трудности и как с ними справиться.

Для начала немного о том, почему мы выбрали для себя Appium. В Яндексе инфраструктура автоматического тестирования в основном рассчитана на использование языка Java, и не хочется городить что-то новое. Тот же Calabash, к примеру, делает упор на Ruby. Appium можно использовать с Selenium Grid из коробки. А приложений у нас много, поэтому хочется удобного запуска тестов в много потоков. Писать их важно под все платформы с использованием одного и того же инструмента, потому что приложения у нас есть и под iOS, и под Android. Кроме того, Appium не требует дополнительной модификации приложения, с которым мы имеем дело в тестах. Большое значение имеет и то, что есть большое сообщество сторонних разработчиков, заинтересованных в дальнейшем развитии этого фреймворка.

Кроме того, хочется выделить основные особенности инструмента:

  • В комплекте с сервером разработчику тестов предлагается инспектор элементов приложения.
  • Фреймворк позволяет управлять приложениями написанными под iOS и под Android.
  • Взаимодействие между тестом и сервером Appium строится на базе WebDriver API.

Но выбором инструмента все не ограничивается, поле из граблей начинается при его непосредственном использовании. Так что остановлюсь на этих моментах подробнее.

Инспектор элементов приложения


Процесс написания тестов для мобильного приложения с использованием Appium очень похож на написание тестов для веб-сайтов. Вы находите какие-то элементы приложения (кнопки, поля ввода, списки) по их селекторам, взаимодействуете с ними и анализируете их состояние. В случае с веб-сайтами для того чтобы понять какой у элемента селектор, мы используем различные веб-инспекторы. В случае с мобильными приложениями каждая операционная система предлагает свое решение. Appium же сделал единое приложение для всех платформ, которое позволяет посмотреть на дерево элементов и на текущий снимок экранов, а так же на значения некоторых атрибутов выбранного элемента.



Но не все так радужно, и вот почему:
  • На момент написания этого поста инспектор работал только под MacOS, но активно ведется разработка версии под Windows.
  • Инспектор показывает не все атрибуты элементов. К примеру, для Android вы не увидите в инспекторе прекрасный атрибут resource id, по которому Appium умеет искать элементы.
  • Инструмент развивается отдельно от сервера. Из-за этого инспектор иногда перестает работать. Например, начиная с версии 0.14, Appium при запуске теста требует обязательно указывать поле device. Инспектор не был рассчитан на такое требование, но зато мог автоматически обновить внутри себя сервер Appium.
  • Иногда показываются не все элементы, которые вы видите глазами на экране телефона. Ситуация редкая, и в ее природе не удалось разобраться.
  • В случае с приложением под Android инспектор может показать некорректный xpath селектор элемента. Если вы попытаетесь воспользоваться автоматически сгенерированным селектором, будьте готовы к тому, что Appium может вернуть совсем другой элемент. Чуть ниже я расскажу подробнее об этой проблеме.

Управление приложениями, написанными под iOS


Принцип работы сводится к преобразованию ваших запросов формата WebDriver API в команды фреймворка для тестирования от Apple — UI Automation. Для запуска тестов на симуляторе вам хватит app файла вашего приложения — никаких интеграций сторонних библиотек не потребуется. Если же хочется гонять тесты на реальном устройстве, то придется немного заморочиться. В целом все работает из коробки: достаточно поставить Appium из npm и установить Xcode. Но давайте рассмотрим подводные камни.

Одна тестовая сессия — одно приложение. В то время, когда выполненяется тест, из указанного при его запуске приложения нельзя выйти без потери сессии. Если вы хотите зайти сначала в Safari, а затем — запустить свое приложение, то у вас ничего не получится. Ниже я расскажу о возможном решении проблемы.

На больших данных Appium работает на небольшой скорости и Appium просто умирает по таймауту. Из-за этого возникает неприятная проблема. Выход из такой ситуации — грамотное продумывание тестовых данных. Избегайте в тестируемом приложении списков с большим количеством элементов.

Xcode не позволяет запустить несколько симуляторов. Так что про параллельный запуск нескольких тестов на одной машине можно забыть. Есть один единственный легальный способ немного скрасить ситуацию. Серверная версия MacOS позволяет пользователю создать две виртуальных машины, с каждой из которых можно работать. Решение дорогое, так как с одного Mac mini получается всего 2 симулятора iOS, но мы остановились на нем из-за отсутствия других вариантов.

Порт для управления браузером — неизменяемый. Этот пункт про тестирование веб-сайтов на симуляторе iOS, которого я обещал не касаться, но его понимание лучше объясняет невозможность параллельных запусков тестов. Дело в том, что при попытке настроить запуск множества эмуляторов на одной железной машине мы не остановились на варианте с виртуальными машинами. Оказывается, если вы заведете несколько учетных записей под одной операционной системой, то каждый из пользователей сможет запустить симулятор. Но тут и возникает описываемая проблема. Appium управляет браузером симулятора через Web Inspector, которой в случае с симулятором слушает порт 27753 на локальном хосте. Порт этот не задать, соответственно при запуске из под разных пользователей каждый из симуляторов попытается занять этот порт и ничего хорошего из этого не получится.

Нельзя выбрать нужную версию iOS на симуляторе. При запуске через консоль симулятор запускается по умолчанию с последней версией iOS, доступной в XCode, и выбрать ее нельзя. Соответственно, чтобы тестировать приложение на версии iOS 6 и iOS 7, вам необходимо скачать Xcode 5 и Xcode 4 и перед запуском тестов выполнять переключение на нужную версию командой sudo xcode-select -switch.

Инструмент не видит прозрачные элементы. В мобильном приложении Яндекс.Карт поверх всей карты лежит прозрачный элемент, отлавливающий действия ваших пальцев. Глазами его не видно, но он есть. А еще есть, к примеру, кнопки приближения и удаления. И их мы видим глазами, но если попробовать с помощью Appium найти элементы, отвечающие за эти кнопки, и попытаться тапнуть по ним, то ничего не получится. UI Automation начинает думать, что данного элемента нет на экране, и необходимо это исправить, промотав экран, но скроллить некуда. Как следствие — ошибка. Решение проблемы — тап по коодинатам. Считываем положение и размеры необходимого объекта. Прибавляем к положению половину ширины и высоты и тапаем. Работает.

Нестабильный симулятор в Xcode 5+. Да, проблемы связаны не всегда с самим Appium. Разработчики из крупных корпораций тоже подкидывают палки в колеса. Так симулятор iOS, начиная с Xcode версии 5, стал с завидной регулярностью падать при запуске. Как следствие у сервера Appium появился аргумент, отвечающий за количество попыток запустить симулятор.

Нет возможности подготовить симулятор. Иногда для тестирования приложения не достаточно пустой операционной системы. К примеру, при тестировании приложения Яндекс.Диск нам понадобилось проверить загрузку уникальных файлов. Хотелось при запуске теста иметь в фотоальбоме свежее изображение. Если вы запускаете тесты на одной единственной машине, то проблемы нет: запускаете тест, который в Safari скачивает вам картинку, а потом запускаете тест, который уже работает с приложением, использующим картинку. Но при работе с Selenium GRID разные тесты попадут на разные симуляторы. Для решения проблемы пришлось слегка модифицировать Appium. На JavaScript был написан тест, который запускал Safari, дергал ручку, которая возвращает текущий timestamp в виде qr кода, и сохранял в фотоальбом полученное изображение. В свою очередь Appium начал следить за еще одним параметром — DesiredCapabilities, и если он принимал значение true, то перед тем как вернуть тестам текущую сессию, локально запускался наш тест на создание файла. Соответственно когда начинался основной тест, в альбомах уже лежала картинка. Загрузка файлов требуется не только в наших задачах, вскоре можно будет обойтись без костылей.

Управление приложениями, написанными под Android


С операционной системой Android у рассматриваемого в этой статье фреймворка тоже все в общем неплохо. На этот раз вызовы WebDriver API преобразовываются в вызовы методов тестового фреймворка от Google — uiautomator. Приложение можно тестировать и на симуляторе, и на реальном устройстве. Местами с Android работать даже удобнее, чем с iOS. К примеру, Android не ограничивает разработчика тестов одним приложением в рамках одной сессии, вы можете входить и выходить из любых приложений неограниченное количество раз за сессию. А запуск тестов на живом телефоне потребует от вас только его подключения к компьютеру, все остальное Appium сделает за вас. Пройдемся теперь по особенностям работы Appium с приложениями под Android.

Сложности

В дереве элементов присутствуют только те из них, что попадают в момент построения дерева в область экрана. В случае с iOS, если элемент находится вне области видимости экрана, то iOS попытается сам до него проскроллить, а вот Android о таком элементе вообще ничего не знает, ведь его нет в текущем дереве. Соответственно, если вам надо тапнуть по кнопке, которую вы сейчас не видите, то придется сначала до нее проскроллить.

Образы Android под Intel, и под ARM. ARM — самая распространенная, но симулятору приходится эмулировать архитектуру процессора, и в итоге все работает очень медленно. Intel — это уже ближе к реальности (хотя бы архитектура процессора не отличается от той, что представлена на системе, запустившей симулятор). Ко всему прочему, сами Intel выпускают ускоритель HAXM, который делает тестирование еще более комфортным, — все работает очень быстро. Но бывают ситуации, когда оказывается что сторонняя библиотека, используемая в приложении, скомпилирована только под ARM. Для таких случаев можно запускать тесты на функциональность, использующую эту библиотеку, на медленных ARM, а остальные — на быстрых Intel.

Ненастоящий xpath. В инспекторе от Appium есть автоматически сгенерированный селектор для выбранного элемента в виде xpath. Но будьте осторожны: для Android он может быть некорректным. Дело в том, что на данный момент Appium не отличает // от /. Ему не важно, на какой глубине находится потомок относительно родителя. И очень часто возвращается не тот элемент, который вы ожидаете. Ситуацию обещают исправить в Appium 1.0. А пока я могу порекомендовать использовать другие виды селекторов — по классу или id — или же стараться проверять xpath, который предлагает вам Appium.

Если ваше приложение ходит в API по https, то вашего корневого сертификата может не оказаться в списке доверенных сертификатов. Так после очередного обновления сертификатов на тестовых серверах у нас перестало работать приложение. Визуально это выглядит как отсутствие интернета, но вы не увидите никаких сообщений об ошибке. Для устранения проблемы придется руками заливать сертификат в симулятор, а потом импортировать его в настройках. Система попросит установить PIN код для телефона. Ставьте, Appium умеет разблокировывать телефон.

OpenGL ES может змедлять тесты. Не стоит забывать, что кроме ускорения в виде HAXM, Android еще использует ускорение графики с помощью OpenGL. Так вот, локально оно, скорее всего, у вас будет работать нормально, и тесты будут бегать относительно быстро даже на ARM. Но на серьезных серверах, где видеокарта далеко не самый важный компонент, OpenGL с большой вероятностью откажется выполнять свою задачу. Поэтому тесты будут идти медленнее, чем на локальном компьютере. Это необходимо учитывать.

В дереве элементов может не быть даже тех объектов, которые сейчас видны на экране. Это очень редкая ситуация, с которой мы столкнулись лишь однажды. В приложении Яндекс.Музыка не получилось найти точку соприкосновения с поисковым саджестом. Как обойти проблему без модификации приложения — не понятно. Разве что только взаимодействие с предполагаемыми координатами элементов поможет.

Проблемы на стороне Android SDK. Если у Apple в симуляторе iOS 7 стало все плохо со стабильностью, то у Google бывают промашки в работе самого Android SDK. Один из последних примеров: в Android 4.2 перестало работать стирание текста. Даже передача в качестве символа кода кнопки backspace не помогала. Как следствие все тесты на переименование текста приказали долго жить. Кроме того, некоторое время назад нельзя было получить снимок экрана, что тоже неприятно. Так что если у вас что-то не работает, не факт, что проблема в Appium.

Искажение входного звукового сигнала. Симулятор искажает звук, поступающий на микрофон, поэтому распознать голос ваше приложение не сможет. Теоретически можно сделать свой пропатченый образ образа Android. Так в симуляторе от Bluestack проблем со звуком нет, но в нем отсутствует uiautomator, так что работать с ним через Appium не получится.

Полезные особенности

Параллельный запуск тестов. В отличие от iOS симулятор Android обладает большой гибкостью в плане настроек и может запускать неограниченное количество своих экземпляров на одной машине. Так вы можете указать симулятору порт, по которому с ним будет общаться adb. Кроме того, что благодаря этому симуляторы будут работать по отдельности, вам еще будет известен идентификатор симулятора, который получается по шаблону emulator-{port}. Затем при запуске Appium вам будет необходимо разбросать сервера по разным портам и задать параметр, указывающий на еще один порт для связи Appium с симулятором (с помощью adb выполняется только малая часть команд). В итоге команда для запуска симулятора будет выглядеть как-то вот так emulator-x86 -avd API18_X86_1 -port 5554 -sdcard 200MB-1.img -no-boot-anim -qemu -m 2047 -enable-kvm, а сам Appium будет запускаться строкой вида appium -a {server address} -p 4721 -U emulator-5554 -dp 6721 --full-reset --nodeconfig register-x86-port-4721.json. Вам останется только менять порты для новых экземпляров симуляторов и серверов Appium. Регистрируете их все в Selenium GRID и получаете инфраструктуру, готовую к параллельным запускам тестов.

Свобода действий. В случае с Android вы можете делать все что угодно: выйти из указанного при запуске теста приложения, зайти в другое приложение, выйти из него и зайти в третье. Все это будет одна сессия. Android позволяет работать со всей своей системой как с одним приложением в рамках одной сессии. Так что тут будет гораздо проще настроить из теста симулятор под ваш тест. Сохранить файлы, выполнить какие-то действия в настройках самой системы.

Поддержка прокси. Когда это может пригодиться? К примеру, для тестирования функциональности вашего приложения, которая зависит от географического региона. Указав прокси из другой страны можно красиво проверить данную функциональность. Нам же пригодился данный атрибут в другой ситуации. Допустим, у вас есть продакшен сервера для приложения и тестинг. Но ваши разработчики не учли возможность переключения окружения в приложении, а вам срочно понадобилось проверить работу приложения на тестовом API. Тут-то и поможет прокси. Поднимаем nginx, пишем просто редиректор на perl, который будет подменять адрес боевого API на тестируемое, и заставляем симулятор ходить через нашу прокси с редиректором. Вот так — без модификации приложения — можно проверять корректность работы с API на различных средах.

Взаимодействие между тестом и сервером Appium на базе WebDriver API


Здесь может быть только одна проблема: если окажется так, что необходимый вам метод еще не реализован. Ознакомиться с отсутствующими методами можно в файле роутинга. В остальном же использование WebDriver API является огромным плюсом Appium. Ведь это позволяет использовать различные сторонние решения, предназначавшиеся для тестирования веб-сайтов, для тестирования мобильных приложений. Так что здесь я перечислю только плюсы от использования Appium.

Поддержка Selenium GRID. Поднимаете сервер Selenium GRID, ставите сервера Appium на машинки, формируете json файлы конфигурации, запускаете с ними Appium. Все. Инфраструктура для параллельного запуска тестов готова.

Отсутствие необходимость подключения лишних библиотек.Ставший классикой артефакт (если мы говорим о Java) selenium-java вам в помощь. Для других языков так же достаточно подключить библиотеку, содержащую клиент WebDriver.

Возможность использовать различные дополнения к WebDriver. К примеру, наши ребята разработали прекрасную библиотеку HtmlElements, предназначенную для удобного хранения селекторов элементов и организации красивой архитектуры ваших тестов по типу шаблона PageObject. Такой подход позволяет использовать уже проверенные на тестировании веб-сайтов практики в тестировании мобильных приложений.

Вывод


Что мы имеем в итоге? Appium пока еще сырой, но быстро развивающийся продукт. Тема автоматизации тестирования мобильных приложений еще только набирает обороты, поэтому Appium — это скорее старый Selenium, чем современный WebDriver. Сервер может упасть в неподходящий момент, тестовая сессия может зависнуть в Selenium GRID (после нашего пуллреквеста, начиная с версии 0.17.7 ошибка исправлена). Документация не всегда актуальна и иногда после очередного обновления о том, что какой-то атрибут вдруг стал обязательным, узнаешь только после изучения исходных кодов продукта. Ошибки исправляются не так быстро, как хотелось бы. К примеру, Appium долгое время не работал под ubuntu. Ошибка была исправлена совсем недавно. Но, как я сказал ранее, продукт быстро развивается, у него (на момент написания поста) уже почти 1000 форков и почти 1200 лайков на гитхабе. Видно, что разработчики следят за пожеланиями пользователей и учитывают их. Если раньше почти вся разработка велась несколькими людьми из Sauce Labs, то сейчас благодаря открытым исходным кодам в появлении новых возможностей и исправлении ошибок участвуют сторонние разработчики. На данный момент, мы рассматриваем использование Appium скорее как эксперимент, но он все больше и больше становится похож на серьезное решение практических задач.

P.S. Пока готовился этот пост, вышли новые версии Appium: 1.0 и 1.1. Пока мы к ним только присматриваемся и не спешим обновляться. С одной стороны, в новых версиях исправлены некоторые проблемы, описанные тут. К примеру, «заработал правильный xpath». Но в версии 1.0 он так «заработал», что при запросе «изображения» мог вернуть «поле ввода». В 1.1 эту проблему поправили. В общем не все еще идеально, и если в одном месте что-то исправили, то не факт, что в других местах не поломали. Ждем стабильности.
Автор: @dolf
Яндекс
рейтинг 486,79

Комментарии (12)

  • 0
    Testcomplete с этого года позволяет тестировать мобильные приложения, насколько помню нативные сразу поддерживались, на Ксамарине с последним обновлением стали, а в будущем обещают и на Кордове добавить.
    • +3
      Мы изначально нацеливались на решения с открытым исходным кодом, подходящие под нашу инфраструктуру, но за информацию спасибо.
  • +1
    Ох, помню с другом — iOS разработчиком вкуривали этот Appium (на другое слово курительное похоже, прямо как облачная платформа Yandex.Cocaine :). Так вот, на тот момент (пара месяцев назад), это было адово геморно, нормальной документации толком не было, примеров тоже. В итоге, чтобы кликнуть на кнопку понадобилось два дня, хотя тут стоит отметить, что с Selenium опыта не было.

    После того же Robotium для Android это было ужасно, я вам скажу.

    Спасибо, что поделились опытом!

    P.S. пока не дочитал до «сессии на Android между приложениями», долго не мог понять зачем для iOS тестов нужно запускать Safari на маке, потом только понял, что Safari внутри симулятора запускался (:
    • +4
      Полностью разделяем вашу боль, так же начинали) Разработчики Appium тоже знают свои минусы и совсем недавно начали делать нормальную документацию appium.io/slate/en/v1.1.0/ с примерами appium.io/tutorial/
      • +3
        Честно говоря, я даже удивлён, что в Яндексе не побоялись использовать такую нестабильную, плоходокументированную штуку.

        Я конечно понимаю, что клёво писать тесты для разных платформ на одном фреймворке, но всё же Robotium гораздо удобнее для тестирования Android приложений.

        Наш QA очень быстро освоил Robotium, да и учитывая поддержку запуска тестов в Gradle (таск connectedAndroidTest и аналогичные) удобно держать unit, интеграционные и функциональные (ui) тесты в одном проекте.

        Мы сразу обговорили правила: в наш код не лезть, особенности реализаций не использовать. Решили, что можно использовать только ресурсы, например строки, для поиска кнопок, полей и так далее без хардкода и независимо от локали и других конфигураций. Было вполне неплохо, не считая нескольких неприятных моментов
        • +3
          в Яндексе и Селениум появился году эдак в 2006-2007 в бете, и ничего, полетел, хоть и не без труда ;)
  • 0
    Цукини с виду хорошая штука.
  • 0
    Сколько боли собрано в этом посте :)
    Мы тоже используем Appium для тестирование под iOS и Android, и нередко сталкиваемся с необходимостью что то подкрутить, подпилить или починить.
    Было бы здорово, если бы работодатель выделял время на создание пулл-реквестов и починку фич необходимых хотя бы для нашей компании.
    • 0
      А что мешает сделать пулреквест в свободное от работы время?)
      • 0
        Политика компании :(
        Конечно можно делать это втихую, но если всплывёт — по головке не погладят…
  • 0
    Xcode не позволяет запустить несколько симуляторов. Так что про параллельный запуск нескольких тестов на одной машине можно забыть. Есть один единственный легальный способ немного скрасить ситуацию. Серверная версия MacOS позволяет пользователю создать две виртуальных машины, с каждой из которых можно работать.

    А вы пробовали, запускать симулятор в отдельной VNC сессии?

    Т.е. создать несколько юзеров на маке и включить им VNC, а потом одновременно залогиниться удалено и запустить симулятор.
    • 0
      Ага, симуляторы у нас так запустить получилось, но в самом аппиуме захордкожены сокеты с расчетом на один симулятор. Поэтому дальше уже проблема в аппиуме. Мы попытались формировать сокеты для каждого симулятора по отдельности, но как-то ничего стабильного у нас не получилось(

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка