
Без качественного и ответственного тестирования не может быть сложного продукта. Для такого тестирования нужен большой парк устройств. Это позволит находить баги до релиза и выдавать качественный продукт. А ещё — максимально оперативно реагировать на обращения пользователей в поддержку и обеспечивать ещё большую стабильность в работе.
У маленькой компании, живущей в рамках одного офиса, одни запросы. Но когда она масштабируется или уводит сотрудников на удалёнку, её потребности разительно меняются. При масштабировании команд и росте числа удалённых сотрудников — от Владивостока до Калининграда — нам становилось сложнее организовывать логистику. Это стало для нас крутым челленджем: здесь есть возможность улучшить процессы и сделать что‑то новое и полезное.
Так появилась наша ферма мобильных устройств VK DeviceHub, которая выросла в современный опенсорсный проект доступный всем - https://github.com/VKCOM/devicehub.
Сегодня наш продукт поддерживает устройства на базе ОС Android и iOS, и мы продолжаем разработку, чтобы расширить число платформ.
Меня зовут Даниил Смирнов, я руководитель команды Android Core R&D, которая развивает VK DeviceHub и другие внутренние решения. Мы вместе с Иваном Левиковым, руководителем тестирования в команде контента, решили улучшить инфраструктуру тестирования и объединили усилия, чтобы построить собственную ферму устройств. И на этом пути преодолели множество технических и организационных вызовов, о которых хотим вам рассказать.
Как всё начиналось
В 2020 году, когда компании массово переходили на удалёнку «буквально на две недели», стало ясно: привычная схема «один стол = много устройств» больше не работает. Если раньше тестировщики и разработчики могли обмениваться устройствами из рук в руки на разных этажах, то с ростом распределённых команд это стало проблематично.

Появился новый интересный вызов — выстроить инфраструктуру, где устройства доступны по запросу, а процессы автоматизации и ручного тестирования живут вместе.
Первые наши попытки организовать инфраструктуру вылились в разномастный парк устройств, объединённых одним хабом. Идея заключалась в том, чтобы положить их в шкаф, где они не будут никому мешать, и удалённо подключаться к ним. Сделав это, мы столкнулись с проблемой: после объединения всех устройств в одну ферму раздельно использовать что‑то для автотестов, а что‑то для ручного тестирования было невозможно.
Наш первый подход — разделить устройства, чтобы минимизировать влияние ручных и автоматизированных тестов друг на друга. Вроде бы план простой и функциональный, но мы продолжали сталкиваться с рядом нюансов. Например, автотесты на физических устройствах флаковали — устройства перегревались, возникали аппаратные сбои. Приходилось тратить очень много времени на дебаги.
Это решение нас не устроило, а написать всё с нуля потребовало бы много ресурсов. Поэтому мы, как и многие, выбрали OpenSTF — популярное опенсорс‑решение для удалённого доступа к устройствам. Но после внедрения мы вновь столкнулись с ограничениями.
Возникали вопросы к безопасности. В исходном OpenSTF было более 180 уязвимостей, которые не считались приоритетом для фикса командой разработки из‑за разных внешних библиотек.
Легаси. Около 70% кода было вроде бы функционально: оно работало. Но мы были ограничены текущей функциональностью. При попытках решать задачи мы часто упирались в необходимость рефакторинга, который никогда не был коротким приключением. Требовался рефакторинг не только этого кода, но и соседних библиотек.
Сложность развёртывания. Первоначальный запуск занимал более 15 минут и требовал ручной работы от нескольких сотрудников.
Ограничения по масштабированию. База данных RethinkDB была функциональной, но не устраивала нас по двум причинам. Во‑первых, она недостаточно поддерживалась и не обновлялась. Во‑вторых, решение не позволяло подключать больше 500 устройств. Мы же планировали масштабироваться до 1 000+.
Сначала мы решили пропатчить OpenSTF — пофиксить уязвимости, обновить зависимости, переписать участки кода. Чем глубже мы погружались, тем лучше понимали: проще построить своё решение. Так появился VK DeviceHub — сначала как форк, а потом как полноценная собственная платформа, заточенная под реальные задачи — челленджи, с которыми мы сталкивались постоянно. Среди них масштабируемое тестирование, высокая стабильность, безопасность и удобство.
DeviceHub: что мы переписали и зачем
Когда проект зарождался, не было отдельной команды: он делался силами инженеров по тестированию как часть задач по написанию автотестов. Но со временем доля использования фермы и требования к ней увеличились — и инженеров, которые занимались её развитием, решили выделить в отдельную команду. За время работы над VK DeviceHub мы не просто адаптировали существующее решение под свои нужды. Мы провели глубокую переработку практически всех ключевых компонентов системы. Делимся, что изменили и улучшили в VK DeviceHub и как сделали его надёжным инструментом для управления устройствами.
Переход с Bower на NPM. Раньше вместо NPM обычно использовали разные собственные решения. Одним из них был менеджер пакетов Bower — неплохой, но со своими нюансами. Поэтому мы отказались от Bower и перевели проект на предсказуемый NPM, часть пакетов встроили, остальные заменили. В итоге получили простую и удобную сборку с современным менеджером пакетов.
Отказ от RethinkDB в пользу MongoDB. У RethinkDB был скоуп особенностей, которые нас не устраивали. Мы решили мигрировать на MongoDB. Проанализировали все запросы, переписали и оптимизировали их — и получили на выходе современную стабильную, быстро работающую СУБД. Это позволило масштабироваться и облегчило сопровождение проекта.
Полный аудит безопасности. Мы обратились к команде информационной безопасности и рассказали, что у нас есть классный проект, но мы не уверены в его безопасности. Кроме мнения нашего главного CISO, у нас не было других подтверждений. Мы попросили совета, как организовать комплексную проверку через Git, протестировать проект корпоративными сканерами, а также провести полноценный пентест. В итоге большинство уязвимостей мы устранили при помощи внутренних решений, обновив библиотеки или заменив зависимости, а оставшиеся — переписав большие фрагменты кода. Самый приятный бонус: теперь наш код автоматически проверяется корпоративными сканерами безопасности при каждом изменении.
Управление аккаунтами через интерфейс. В STF создание и настройка пользователей делалась вручную — напрямую в RethinkDB через разные запросы. Когда пользователи добавляются редко, такая концепция оптимальна. Но нам хотелось автоматизировать процесс. Мы добавили интерфейс для управления учётными записями, чтобы можно было создавать сервисные аккаунты для разных задач. Также сделали API‑интеграции, чтобы выдача прав могла происходить автоматически в рамках единой политики управления данными.
Оптимизация графики и трафика. OpenSTF передавал изображения в JPEG, и картинки имели большой вес, из‑за чего сеть перегружалась. Мы постарались расширить канал, и в рамках одной сети всё было оптимально. Но когда коллеги, выходящие поработать на берег Байкала, начали жаловаться, что иногда появляются пиксели, мы поняли, что в эту проблему нужно вгрызаться глубже. В итоге мы провели полный рефакторинг, и на замену JPEG пришёл WEBP. Изображения стали меньше нагружать сеть, быстрее загружаться, а для удалённых коллег мы добавили адаптивную картинку.

Полноценный ввод текста через KeyBoardService. ADB Shell Input из исходного опенсорсного решения не поддерживал кириллицу, эмодзи и часть символов. Мы поняли это, когда коллега начал тестировать армянскую локаль приложения. Вызов был необычным и интересным. В итоге написали сервисную клавиатуру, принимающую текст через intent — теперь поддерживаются все символы, в том числе алфавиты других языков.
Система бронирования и инвентаризация. Раньше у нас часто возникала проблема: кто‑то брал популярное устройство и держал его у себя несколько дней, забыв нажать кнопку «Отпустить устройство». Мы решили разобраться. Вначале опросили коллег и выявили проблемы, требующие решения. Следующим шагом упростили систему бронирования устройств и сделали её более понятной. Теперь в системе есть таймер — видно, до какого времени устройство занято. Также можно легко продлить бронь или освободить устройство. В интерфейсе отображаются инвентарные номера, MAC‑адреса, серийные номера и тип push‑сервисов (GMS/HMS). Мы также оптимизировали внутреннюю логику, чтобы всегда было понятно, кто сейчас пользуется устройством.
Хоткеи и улучшения интерфейса. Некоторые коллеги работали с разными хоткеями, которые отправляли на устройства. Таких опытных ребят сразу было видно — спроси его ночью про любимые ADB‑команды, и он тут же выдаст целый список. Нам такие сложности были не нужны, но некоторые из этих действий могли бы пригодиться и другим. Поэтому мы добавили удобные хоткеи для самых популярных задач: смены темы, включения и отключения Google‑сервисов, смены языка и размера шрифта. Интерфейс стал современнее и больше похож на наш корпоративный стиль.
Как построить свою ферму Android-устройств и эмуляторов
Развернуть ферму устройств кажется просто только на первый взгляд. На деле всё зависит от ваших задач, количества устройство и амбиций.
Если вы — небольшая команда, у которой всего десяток устройств, не стоит изобретать велосипед. Берёте обычный компьютер, ставите на него Docker Compose, подключаете USB‑хаб, втыкаете в него телефоны — и вуаля, у вас своя мини‑ферма. Всё работает стабильно, просто и понятно. Такой способ отлично подходит для старта или локального тестирования.

Но стоит количеству устройств перевалить за полсотни, как простые решения перестают работать. Здесь уже нужна мастер‑нода, и желательно Kubernetes или хотя бы SystemD‑юниты для управления сервисами. К мастер‑ноде подключаются воркеры, а к ним — USB‑хабы с устройствами. Оптимально объединять по 10 устройств на одном хабе, чтобы избежать перегрева и проблем с питанием. Воркеры можно запускать на отдельных машинах, а если устройств становится больше ста, масштабируйте горизонтально — добавляйте воркеры и мастера, чтобы система оставалась устойчивой.

Если ваша задача — гонять автотесты и не привязываться к железу, эмуляторы — отличный выбор. Их удобно запускать в Kubernetes или KTS, а порты пробрасывать к ADB‑серверу, который работает рядом с OpenSTF или другим управляющим ПО. Это позволяет быстро масштабировать инфраструктуру и не зависеть от физического износа устройств.
А если хочется всё и сразу: и эмуляторы, и реальные устройства? Здесь на помощь придёт гибридная схема: один мастер, два воркера — один для физических устройств, второй для эмуляторов. Такая архитектура отлично работает, если у вас до 100 устройств каждого типа. Если парк растёт, просто добавляйте воркеры и мастера для кворума и отказоустойчивости. Главное — не забывать увеличивать количество мастеров по мере роста числа воркеров. На три воркера — три мастера, на пять — пять и так далее. Это обеспечит стабильность и лёгкость управления.
Как выглядит наша ферма
Мы ВКонтакте прошли путь от шкафа с системным блоком до полноценной серверной стойки. Сейчас у нас на отдельных полках аккуратно размещены устройства в подставках. Для USB‑хабов мы сделали специальные одноюнитовые крепления, которые напечатали на 3D‑принтере. После множества прототипов пришли к простой, но удобной конструкции с укороченной полкой — и больше никаких болтающихся проводов.
Все кабели промаркированы, а информация о маркировке внесена в интерфейс фермы. Теперь найти нужное устройство — дело пары секунд. Провода собраны в косы, чтобы не мешались и не ограничивали доступ к устройствам. Для подключения используем серверные юниты на Intel Xeon — к одному такому можно подключить до 50 устройств. В качестве воркеров отлично себя показали Mac mini на Debian: к одному маку подключаем до 40 устройств.

Стоимость сборки одной фермы Android-устройств
Разбираемся на примерах.
Физические устройства. Возьмём Galaxy S25+ — мощный и популярный смартфон. Его цена — около 90 тысяч рублей на маркетплейсах. Но не забывайте: физические устройства со временем устаревают, изнашиваются, требуют обновления и обслуживания. Поэтому планируйте парк с запасом и учитывайте, что через несколько лет часть устройств придётся заменить.
Эмуляторы. Эмулятор, развёрнутый на сервере, обойдётся в 10–30 тысяч рублей. Это дешевле, но здесь тоже есть нюансы: сервер должен быть достаточно мощным, чтобы тянуть нужное количество эмуляторов без просадок по производительности.
Попробуем представить, сколько потенциально нужно устройств. Рассмотрим константную величину — время прогона одного теста. Мы считаем, что оно должно быть не более 30 секунд, а время прогона всех автотестов на всех устройствах — не более 240 секунд. Так мы сможем получить результат по прогону в кратчайшие сроки и понимать, вливается код или нет.
Получаем следующую зависимость:
Если у вас до 100 автотестов, достаточно 12 устройств и двух серверов. По 8 эмуляторов на сервер — это оптимальный баланс между производительностью и стабильностью. Не забывайте добавить мастер‑ноду для управления.
Если автотестов 1 600 — готовьте 200 устройств и 26 серверов. А если серверов становится больше десяти, обязательно добавляйте вторую мастер‑ноду для резервирования. Чем больше кластер, тем сложнее его поддерживать, и отказ одного мастера не должен парализовать всю систему.

Какие числа мы получаем при расчёте стоимости ферм:
Минимальная конфигурация (100 автотестов): 3 сервера, 12 устройств — около 300 тысяч рублей.
Крупная ферма (1 600 автотестов): 26 серверов, 200 устройств — более 2,5 миллиона рублей.
Это примерные числа, но они дают понимание масштаба инвестиций. Если у вас уже есть часть железа — отлично, используйте его по максимуму.
Сейчас DeviceHub — это более 3 000 автотестов, которые прогоняются одновременно, 70+ серверов, более 700 эмуляторов на разных фермах, физические устройства, а также свыше 400 прогонов в день. Это высоконагруженная система, которую действительно интересно развивать.
Автоматизированный шкаф выдачи устройств
Также мы реализовали в DeviceHub ВКонтакте ещё одну полезную функцию. Раньше мы вручную отслеживали, кто из коллег какое устройство взял. Это было весело, но неэффективно: устройства терялись, путались, забывались. Теперь мы разработали систему бронирования, позволяющую заранее резервировать нужное устройство. Автоматизированный шкаф с камерой и машинным зрением фиксирует момент выдачи релевантного устройства.
Решение компактное, его легко развернуть в любом офисе. Если нужно устройство — оставляете заявку, мы подключаем его в ферму, и вы получаете к нему доступ через DeviceHub или физически.
Вместо заключения
Разработка VK DeviceHub стала для нас невероятно ценным опытом построения отказоустойчивой и высоконагруженной инфраструктуры в условиях постоянного масштабирования. Переход на кастомное решение позволил устранить огромное число неприятных уязвимостей и ускорить обработку запросов в несколько раз. У нас получилось создать платформу, которая сегодня обслуживает 3 000+ параллельных тестов. Кластер из 92 vCPU и 700+ эмуляторов стабильно работает даже при пиковых нагрузках, а интеграция машинного зрения в процесс выдачи устройств свела человеческий фактор к нулю. Эти решения уже экономят командам VK сотни часов ежемесячно.

Мы стабилизировали работу платформы c Android и весной 2025 года запустили поддержку iOS. Это сложнее: в устройствах на Android у нас есть доступ к железу и ПО, а iOS — очень закрытая система. Для Apple пришлось придумать обходные решения: эмуляцию через ESP32, интеграцию с WebDriverAgent и создание гибридного пула устройств. В следующей статье мы подробно расскажем, как решали проблемы с подключением iOS‑устройств.
Создание собственной фермы устройств — это интересный вызов и отличный способ ускорить релизы и повысить качество продукта. Не бойтесь экспериментировать, масштабировать и автоматизировать!
Если остались вопросы — приходите в комментарии.
AlGut
Спасибо за статью. А как вы решили проблему ускоренной деградации батарей? Постоянное нахождение устройства в режиме зарядки от usb-хаба приводит к повышенному износу батареи и к её "вздутию" в некоторых случаях менее чем за год.
di_smirnov Автор
Было два варианта - научиться подкидывать аккумуляторы, что мы практически и сделали, но в итоге дешевле и проще оказалось начать охлаждать стойку внутри. При стабильной температуре в 21 градус девайсы стали вздуваться крайне редко (1 - 2 устройства в год из 70)
Kreatif74
В обычных условиях, мы выяснили, что АКБ умирает в среднем за 6-8 месяцев
Как верно отметил Даниил - при понижении общей температуры ближе к 21 градусу проблема минимизировалась
А за температурой устройств мы наблюдаем отдельно)