Привет, Хабр. Меня зовут Даниил Смирнов. Я руководитель команды Android Core R&D в VK.

Не так давно я уже рассказывал о DeviceHub — инструменте от команды VK для одновременного управления несколькими смартфонами. Он позволяет тестировать мобильные приложения и сайты в фермах, состоящих из сотен гаджетов. Подробнее почитать об этом можно здесь.

Изначально DeviceHub мог работать только с Android-устройствами. Но теперь, после обновления, инструмент поддерживает и iOS-устройства.

Расскажу в статье, для чего нам понадобилась поддержка iOS и с чем мы столкнулись при внедрении новых возможностей.

Как мы шли к ферме для удалённого доступа к девайсам

Все бизнес-юниты VK активно разрабатывают продукты для мобильных платформ и тестируют работоспособность приложений на разных устройствах. Представьте: идёт январь 2020 года, вы с командой работаете в одном офисе, встречаетесь, обсуждаете проекты и вместе тестируете прототипы. Тогда с этим не возникало проблем — команды могли получать доступ к физическим устройствам в рамках одного офиса и тестировать свои наработки на разных устройствах iOS или Android.

Но с общим переходом на удалённый формат работы в период пандемии, ситуация кардинально изменилась. Чтобы команды могли и дальше активно разрабатывать продукты и тестировать их, нужно было рассылать устройства каждому вовлечённому в процессы. Это было долго, сложно и дорого. Поэтому мы решили адаптироваться к новым условиям — и начали работу над переходом к фермам мобильных устройств с возможностью удалённого доступа.

Уже после первой итерации стало очевидно, что писать свою ферму с нуля будет очень дорого. Поэтому мы решили применить популярное open-source решение — OpenSTF. Но и здесь всё оказалось непросто. Чтобы выбранный инструмент справлялся с текущими задачами, нам приходилось непрерывно оптимизировать его. Но доработок хватало ненадолго. В итоге мы поняли, что лучшее решение — не брать чистый open source, а полностью перенести доработки на нашу сторону. Так мы создали собственный форк, выросший в полноценное решение — VK DeviceHub.

Сейчас VK DeviceHub используется не только для ручного тестирования, но и для автотестов. Сегодня наша ферма — это 3 000 автотестов, которые прогоняются одновременно, 70+ серверов, более 700 эмуляторов на разных фермах, физические устройства, а также свыше 400 прогонов в день. 

Наша физическая ферма мобильных устройств расположена в отдельном кондиционируемом помещении. В один серверный юнит мы подключаем до 50 девайсов. Также для подключения устройств в качестве серверов используем Mac mini. Он один выдерживает подключение до 40 смартфонов.

Примечание. Больше об опыте оптимизации работы с автотестами и нашей ферме мы рассказывали в предыдущих докладах «Как мы повысили эффективность фермы эмуляторов и ускорили UI-автотесты на Android» и «DeviceHub: облегчаем работу с устройствами и эмуляторами».

Зачем нам понадобился iOS в ферме?

Изначально VK DeviceHub был ориентирован на работу с устройствами на базе Android и позволял закрыть потребности всех участников процесса тестирования и разработки без необходимости закупки огромного количества Android-устройств.

С Apple всё несколько проще, поскольку нет многообразия устройств от разных производителей с неочевидными особенностями. Поэтому в теории было достаточно закупить устройства нескольких версий под основные сценарии разработки и тестирования. Но под влиянием внешних факторов ситуация изменилась.

  • В феврале 2025 года Apple изменила корпоративные правила. Теперь каждое устройство, на котором нужно проверить продукт, надо добавлять в аккаунт TestFlight. Это создало дополнительные издержки и трудности.

  • Часть специалистов продолжает работать удалённо или часто ездит в командировки. При этом нередко им может понадобиться что-то проверить на iOS-устройстве. Но отправлять iPhone 16 Android-тестировщику, который несколько раз в год будет использовать на нём отдельные сценарии — нерационально.

  • Иногда для тестов нужен быстрый доступ к разным версиям iOS. При использовании физических устройств здесь могут возникать трудности. Например, нам надо протестировать приложение на последней версии, а обновление на смартфон ещё не пришло. Или наоборот — телефон уже обновился, а нужно посмотреть, как ведёт себя обновление на старой версии.

Учитывая это, мы решили мигрировать с индивидуальных девайсов на столе к устройствам в облаке.

С чем мы столкнулись?

Поняв, что нам нужна ферма мобильных устройств, мы начали изучать рынок и существующие инструменты. Поиск не увенчался успехом:

  • в открытом доступе есть либо фермы только для автотестов, либо фермы только для iOS — ничего универсального под наши запросы;

  • релевантных библиотек для работы нет: некоторые из них сломались совсем недавно (например, в iOS 18), а другие — давно, и про них забыли;

  • есть несколько старых репозиториев с интересными идеями, но владельцы забросили их.

Так мы поняли, что надеяться на готовое решение не стоит, и начали изучать доступные возможности реализации. Требования были довольно простыми — ферма должна позволять получать картинку, а также передавать на устройство нажатие и ввод текста и работать так же круто, как наша Android-ферма. 

Начали с самой сложной задачи — получения картинки.

Получение изображения с iOS

Есть несколько основных вариантов получения изображения с iOS:

  • HLS через ReplayKit;

  • AirPlay;

  • по проводу;

  • AVFoundation (он же QuickTime);

  • Appium WebDriverAgent.

Но у каждого из них есть свои особенности:

  • HLS через ReplayKit — самый простой и очевидный вариант. Чтобы протестировать его, мы нашли open-source приложение, которое доработали под себя. Но такой подход оказался неоптимален для нашего кейса — на выходе мы получили от 4 до 20 секунд задержки отображения, что критично. Поэтому от варианта отказались.

  • AirPlay — интересное решение, но проприетарное. Соответственно, чтобы работать с ним безопасно, нужны разрешённые интерпретации. А они не всегда работают стабильно и зачастую не могут быть развёрнуты без дополнительных сервисов.

  • Вариант с подключением по проводу на первый взгляд простой и надёжный. Но на практике переусложнён: нужна карта захвата, механизм получения картинки с карты захвата, алгоритм передачи картинки через браузер. И на каждом этапе этой цепочки потенциально может произойти сбой, поэтому от этой идеи тоже отказались.

  • AVFoundation (он же QuickTime) — программа, которая позволяет получать картинку с экрана телефона. Решение удобное и популярное, но iOS 17 — последняя версия с поддержкой QuickTime.

В поисках оптимального решения мы наткнулись на статью, где одна из команд делилась похожим кейсом. Ребята успешно применили Appium WebDriverAgent — реализацию WebDriver iOS, которая позволяет автоматизировать работу и управлять устройствами через XCTest. Изучив их опыт, мы решили рассмотреть инструмент подробнее и попробовать применить его для своих задач.

Подробнее о работе с Appium WebDriverAgent

WebDriverAgent работает по следующему принципу:

  • Appium tests при запуске по HTTP отправляют запросы на Appium server;

  • Appium server отправляет запросы на порт 8100 устройства, где работает WebDriverAgent;

  • WebDriverAgent через системные вызовы выполняет нужные действия с iOS.

Всё предельно просто.

Для запуска WebDriverAgent на устройстве мы используем простой алгоритм:

  • открываем проект в Xcode;

  • собираем его;

  • запускаем тесты из него.

Примечание: для физического устройства будет нужно изменить bundleID.

После запуска на порту 8100 устройства станет доступен WebDriver сервер, а на порту 9100 — MozJpeg поток с изображением с экрана устройства.

Чтобы взаимодействовать с WDA из фермы и запускать всё автоматически, мы сделали несколько доработок.

  • Реализовали отправку команд из модуля фермы в WebDriverAgent на устройстве. Подробнее об этом можно почитать здесь.

  • С помощью USBMux пробрасываем порты с устройства на хост, чтобы не ходить через сеть. Подробнее об этом можно почитать здесь.

Примечание: USBMux — демон, который обрабатывает связь по USB с устройствами iOS (включая связь из iTunes). Когда устройство подключено, USBMux взаимодействует с ним, как посредник для связи с устройством. Изначально мы использовали pymobiledevice3, но решили уменьшить число внешних зависимостей и перешли на использование USBMux из js. Подробнее о нём можно прочитать здесь.

  • Предусмотрели автоматическое переподписывание сертификата приложения с помощью небольшого скрипта:

xcodebuild\
-project WebDriverAgent.xcodeproj\
-scheme WebDriverAgentRunner\
-destination “id=$deviceld”\
-allowProvisioningUpdates\
test | tee/tmp/wdalog.txt & 
wdapid=$!

В результате собрали требуемую конфигурацию для получения картинки с iOS. 

Но важно отметить — наша ферма работает на Kubernetes, то есть использует Linux. Xcode там нет. Поэтому мы разместили рядом Mac mini на macOS, а на нём развернули самописное приложение STF iOS Provider. Оно взаимодействует и с USBMux и с Xcode — и выступает в роли Appium-клиента для WebDriver, который работает на устройстве.

Передача нажатия и ввода текста

Есть несколько основных способов передавать нажатия и ввод текста:

  • через XCTest;

  • с помощью внешнего устройства.

Мы решили начать с WebDriverAgent и XCTest.

XCTest

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

Но для полноценной фермы этого недостаточно. Нам также нужно заглядывать «под капот», как минимум — иметь возможность изучить логи. 

Примечательно, что для Android есть решение, предоставляющее такие возможности, — Android Debug Bridge (ADB). Так, ADB позволяет:

  • собирать логи;

  • устанавливать приложения;

  • управлять устройством;

  • проверять статусы и состояния;

  • настраивать устройства под задачи.

Соответственно, нам нужен был инструмент со схожим набором возможностей для iOS.

Быстрый поиск показал, что нужный инструмент уже есть — iOS Development Bridge. Он подошёл под наши запросы, потому мы решили его применить сразу для нескольких задач, среди которых:

  • получение информации об устройстве;

  • получение файлов с устройства;

  • чтение логов.

Примечание: iOS Development Bridge отдаёт логи не целиком, а чанками. Чтобы парсить их, мы придумали несколько вариантов. Подробно об их реализации можно узнать здесь.

Что из этого получилось

В результате мы выстроили простой пайплайн передачи нажатия и ввода текста с помощью WebDriverAgent:

  • iOS-девайс с установленным WebDriverAgent подключается к машине на macOS для управления;

  • машина на macOS, в свою очередь, подключена к общему кластеру VK DeviceHub;

  • устройства обмениваются данными о состоянии через ZeroMQ и базу данных.

В итоге у нас получилось подключить живые iOS-устройства и симуляторы — всё заработало стабильно и плавно.

Немножко RnD: прототипы

У XCTest и механики работы с ним есть нюансы — и мы проводили смежные исследования.

V-USB

В рамках одной из своих гипотез мы хотели взять Arduino, оснастить его набором резисторов с конденсаторами, подключить к порту iPhone и попробовать понажимать кнопки. 

Довольно быстро оказалось, что подобная реализация уже есть — V-USB. Это программная библиотека, позволяющая получить поддержку USB на AVR-микроконтроллерах, например Arduino Nano или Uno, и эмулировать HID-устройство Human Input Device.

В теории решение хорошее, но для нас оно оказалось недостаточно быстрым и стабильным. 

Поэтому мы решили, что нужен контроллер сразу с HID. Так мы нашли AtMega32U4.

AtMega32U4

ATmega32U4 — 8-битный микроконтроллер от компании Microchip (ранее Atmel). Его вычислительное ядро, память и периферийные модули расположены на одной микросхеме. Это решение для проектов, где нужно прямое подключение к компьютеру без лишних компонентов. Работает быстро и почти безотказно.

Но у него есть издержки — ATmega32U4 занимает порт, поэтому остальные манипуляции с девайсом приходится проводить через сеть. Соответственно, и зарядку нужно подкидывать на аккумулятор или выполнять через MagSafe. 

То есть почти успех, но чуть-чуть не хватило. 

Финальная итерация

В поисках решений мы наткнулись на ролик с китайскими фермами для майнинга мобильных криптовалют или лайков, для которых нужно нажать на экран смартфона. После беглого ресёрча поняли, что подобные решения можно приобрести на тесты.

Мы решили попробовать — нашли друзей в Китае, заказали комплект и начали его тестировать. Довольно быстро увидели точки роста в существующей реализации и погрузились в свои доработки с реверс-инжинирингом. Так мы создали механизм, работающий на ESP — bluetooth-мышь и bluetooth-клавиатуру, которыми управляем с помощью команд, поступающих через serial port. 

Немного о результатах проделанной работы

  • Мы подключили Mac mini, на котором хостилась iOS-ферма, в саму ферму, чтобы заходить в Mac mini не по SSH, когда что-то сломается, а через ферму.

  • Мы получили универсальный модуль, который позволяет подключить ферму к нам — или практически любой девайс, который работает с VNC, в проект, развёрнутый у вас. 

    • Например, уже сейчас с помощью VK DeviceHub мы можем тестировать работу приложений на умных девайсах (например, смарт-часах), Android Auto, телевизорах и не только. В перспективе мы также планируем добавить поддержку Tizen и WebOS.

  • После обновления VK DeviceHub поддерживает iOS и новый интуитивно понятный интерфейс, собранный на VKUI-компонентах. Также мы устранили более 170 уязвимостей в коде.

  • Сценарии использования VK DeviceHub не ограничиваются автотестами. Инструмент позволяет получить удалённый доступ к устройствам для агентов поддержки и девайсам для разработки и тестирования фич.

  • Docker-образ VK DeviceHub уже скачали более 5 000 раз пользователи более чем из 8 стран. Отчасти такая география обусловлена тем, что в инструменте реализована поддержка 12 языков.

  • Специалист с опытом поднимет DeviceHub примерно за 8 минут. Среднее время решения проблемы в чате open source — 15 минут.

Краткое послесловие

Уже сейчас VK  DeviceHub покрывает 99% сценариев мобильного тестирования ВКонтакте и даёт возможность проводить миллионы автотестов в месяц. При этом решение непрерывно развивается — например, в перспективе мы планируем поддержать расширенную удалённую отладку. Она упростит работу тестировщиков и даст им больше возможностей.

При этом VK DeviceHub и мы, как команда его разработки, полностью открыты: инструмент со всеми изменениями можно найти в репозитории GitHub, его образ — в Docker Hub, а любой обратной связью можно поделиться в чате DeviceHub в GitHub или ВКонтакте.

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