Привет, Хабр! Меня зовут Руслан, я — автотестировщик в QA-агентстве «Кавычки». Из этого можно понять, что мы в агентстве занимаемся только тестированием во всех его проявлениях, а меня зовут Руслан. Отлично, идем дальше. Когда какая-то проблема начинает сильно докучать, то даже тестировщики могут что-то создать (ну или сломать это к черту, чтобы не мешало). Это статья как раз про тот случай, когда наша проблема перешла совместимый с жизнью болевой порог, и нам пришлось решить ее с помощью собственной разработки.

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

Кому вообще стоит напрячь зрение и прочитать эту статью? 

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

Disclaimer

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

Что заставило тестировщиков кодить

Для начала пройдемся по терминам: облачные фермы (AWS, BrowserStack и т. д.) — это разнообразие различных устройств и браузеров, с помощью которых можно полноценно проводить тестирование, внедрять автоматизацию, логировать состояния устройства и т.д.

Тогда возникает логичный вопрос: а зачем заморачиваться и придумывать что-то новое, если уже есть готовые решения, например, тот же BrowserStack? (Действительно!) Изначально мы, как и многие тестировщики, пользовались народным и простым решением для тестирования IOS — BrowserStack. Однако у него (как и у других похожих инструментов) есть ограничения, которые отражаются на качестве тестирования и количестве нервных клеток тестировщиков.

Проблемы, с которыми мы столкнулись, работая с BrowserStack:

  • Это не живые устройства, а их эмуляция

Именно поэтому работа продукта в BrowserStack может отражаться одним образом, а на живом устройстве мы увидим совсем другое. Как итог, можем пропустить баг или докопаться, что баг есть, а на живом устройстве его нет и никогда не было.

  • Медленная скорость работы облачных ферм

Зачастую все сервера облачных ферм находятся за пределами России, поэтому происходит слишком большой лаг. Иногда настолько большой, что можно успеть сгонять за пивом и вернуться. А если без шуток, то иногда просто невозможно ничего сделать и тем более качественно протестировать.

  • Ограниченный функционал

Так как это эмуляция, то не все нативные сервисы возможно использовать, т. е. нельзя использовать номер телефона, вставить свою симку, подключить Apple ID или какие-то другие нативные сервисы.

Далее примеры нашей боли. Просьба: впечатлительным с хорошим зрением отойти от экрана.

Это Gif, поэтому не слышно, как горит тестировщик
Это Gif, поэтому не слышно, как горит тестировщик
Видео для тех, кому было недостаточно плохо от первого
Видео для тех, кому было недостаточно плохо от первого

Итого, наш путь осознания проблемы выглядел так:

  1. Тестирование IOS в BrowserStack все больше подводило, а нас, в свою очередь, начинало подводить психическое здоровье. Потому что приходили клиенты и жаловались, что мы пропускаем баги. А мы даже и не видели эти баги, в BrowserStack их просто не было.

  2. Команде приходилось занимать очередь, чтобы протестировать IOS. Изначально мы были очень маленькой компанией, а потом стали расти, но из-за ограниченных ресурсов количество аккаунтов в BrowserStack оставалось прежним. Поэтому в дни релиза начинался Ад и Израиль.

  3. Для того, чтобы как-то разгрузить очередь, мы периодически закупали живые устройства и рассылали по ребятам. Это достаточно дорогое удовольствие, и не всегда хватало ресурсов, поэтому кому-то приходилось страдать.

  4. Стало понятно, что так продолжаться не может, и мы решили попробовать сделать что-то свое.

Очередь на ферму в дни релиза
Очередь на ферму в дни релиза

Техническая часть

Начнем с того, из чего состоит ферма:

  • IOS устройства, подключенные к серверу и имеющие доступ в сеть;

  • Сервер;

  • Юзер, который подключается к серверу, и через какой-нибудь простой веб интерфейс видит устройства и выбирает нужное.

Пожалуй, электричество сюда вписывать не буду. А так все.

Теперь пройдемся по железу и затронем техническую часть более подробно.

Управление состоянием телефона

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

  • Инструмент в формате сервера, который будет принимать и обрабатывать действия пользователя в real-time режиме;

  • Возможность реализации на каких-нибудь популярных языках программирования, чтобы мы случайно не начали писать на Jython;

  • Разработка не только под Mac OS, линуксоиды меня поймут.

Под наши критерии подходил только Appium. Да, можно было сделать франкенштейна, собрав воедино множество инструментов, чтобы покрыть все наши хотелки. Но давайте честно, мы искали простой и бесплатный вариант. Из того, что могло бы быть, но не случилось: Ranorex, Automator, Selenium и т. д. Что-то из этого не подошло, потому что не open source, что-то было сложно, а что-то нельзя использовать с IOS. Поэтому Appium. Я не буду подробно рассказывать, что это такое. Если вы с ним не знакомы, то сходите по ссылочке и познакомьтесь. Лучше чем Appium про Appium никто не расскажет.

Здесь должен был быть happy end, но зачем. У Appium есть проблема, которую нам до сих пор не удалось решить простым способом. Appium не позволяет сидеть более чем одному человеку на ферме. Мы точно знаем, что это из-за портов в самом Appium, который может работать только с одним соединением одновременно. Одним из очевидных вариантов решения мы рассматривали контейнеризацию множества серверов Appium с разными портами, однако, это другой уровень требований по знаниям и железу, поэтому мы все еще в поисках иного варианта, более простого. Возможно, вы его подскажете. Ну пожалуйста.

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

Подробнее можно здесь посмотреть

Процесс управления состоянием телефона выглядит так: действие пользователя (например, клик) мы переводим в скрипт (скрипт написан на Python), подключаются библиотеки Appium, и мы просто передаем эти скрипты на телефон через Appium.

Передача изображения с экрана телефона до юзера

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

Мы прошли нелегкий путь от передачи скриншотов до настройки HLS потока:

Попытка № 1

Первая идея была проста: по тактовой частоте процессора делать скриншот экрана устройства и отправлять его пользователю. Скриншоты делались быстро, выглядели качественно (не стыдно на авку поставить), но из-за того, что это JPG формат — размер файла был слишком большим и в среднем доходил до пользователя с задержкой — 5 -10 сек. Так как проблема была в размере, а размер имеет значение, то мы пошли дальше.

То, что приходилось видеть с передачей изображений в JPG
То, что приходилось видеть с передачей изображений в JPG

Попытка № 2

Мы перешли к низкокачественному PNG. Да, потеряли в качестве, но зато увеличили скорость передачи почти в два раза. И даже такой скорости оказалось недостаточно, чтобы адекватно пользоваться телефоном, не говоря уже о тестировании.

Посмотрите, как это было больно:

Попытка № 3

Мы решили попробовать HLS поток. Как вы поняли, нас посещали все более грандиозные идеи. Как выглядит работа HLS потока: происходит сбор картинок в буфер, из буфера собирается видеофайл и бесконечно транслируется пользователю.

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

Помучавшись, мы вернулись… И к кому? Правильно, Appium. За время наших поисков передача изображений через Appium была доделана разработчиками. Задержка составляла буквально секунду.

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

Если вы не поняли, то выглядит это так :)
Если вы не поняли, то выглядит это так :)

Важно: не забывайте, что скорость передачи изображения все еще зависит от пинга до сервера. Поэтому держите небольшую рекомендацию: если вы не хотите материть нас и писать слова любви в какое-нибудь «ебаное IT» — располагайте все свои сервера с фермами хотя бы в своем городе или области, или на худой конец — в своей стране.

Двустороннее интерактивное соединение

Итак, у нас есть телефон, есть пользователь, который должен видеть этот телефон и тыкать в скриншот. Не хватает только одного: все это должно происходить одновременно. Иначе что это за real-time такой? Поэтому единственным возможным решением были WebSockets. Это технология позволяет установить и поддерживать двустороннее интерактивное соединение между клиентом и сервером в режиме реального времени. И что очень важно — технология защищена. Злоумышленники, получившие доступ к вашей сети, могут просто увести телефоны, перебив айдишники. И вместо рабочей фермы вы получите кучу телефонов, которые висят у вас на зарядке, и смс-ки с незнакомого номера: «скинь пятихатку».

Как выглядит работа фермы в итоге: у нас есть телефон, мы передаем через Appium изображение до юзера. У нас есть юзер, он выполняет действие над этими скриншотами, которые получает до Appium-сервера. Appium через свои инструменты имитирует эти действия на телефоне. Все это защищено подключением WebSockets.

И все. Да, вряд ли мы сможем посмотреть какие-нибудь видосы в 4к, но для тестирования базовых вещей — самое то. Если вы, конечно, не тестируете видеопотоки.

Схема работы фермы
Схема работы фермы

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

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

Из ее преимуществ:

  • Привязка к нативным сервисам;

  • Установка любых приложух;

  • Поведение тестируемых продуктов реально, так как мы взаимодействуем с живым устройством, а не эмулятором, как было с BrowserStack;

  • Наличие сервера, что позволяет дополнительно настроить инструменты по анализу сетевого трафика, менять VPN, локацию и т. д.

Из ее не преимуществ:

  • Возможность использования для одного человека — это до сих пор самый большой минус;

  • Это не протестировано — мы же тестировщики. Плюс, нам бы хотелось получить мнение со стороны;

  • Отсутствие трансляции звука. Но это скорее общий минус всех облачных ферм. Пока это нигде не реализовано. А если реализовано — напишите в комментах.

Так сейчас работает наша ферма. Да, она существует:

О главном или что нужно, чтобы запустить ферму

По железу:

  • Сервер, где все это будет крутиться. Еще лучше — купить какой-нибудь USB хаб, чтобы можно было заранее подключать телефоны;

  • Телефоны под управлением IOS.

По скиллам:

  • Базовые знания командной строки будь то Linux или PowerShell, или еще что-нибудь эдакое;

  • Придется работать с сеткой; нужно уметь открыть порт; поднять Nginx; запрогать что-нибудь в Vim, сохраниться и еще, если повезет, выйти;

  • Нужно понимать, что действия, которые совершает пользователь для ретрансляции, написаны на Python. Некоторые вещи можно переделать под себя, если что-то по вашему мнению неудобно. Можно дописать, если вы придумаете какие-нибудь фичи;

  • Ну и никуда без этого: любое программирование — это просто напросто умение гуглить.

Перед тем, как я поделюсь ссылкой на гит, хочу обратить внимание на важный момент. Наша разработка распространяется по Beerware лицензии. Ее суть проста: если пользователь продукта встречает автора и считает программу полезной, то он угощает его пивом. (Если что, мы за Гиннесс, сидр или «Атомная прачечная»).

А вот и ссылка на на гит, в котором есть гайд (guide, you know?) о том, как развернуть эту ферму у себя. Кстати, мы тут запилили чатик в телеге чисто под обсуждение фермы, если будут вопросы/предложения и что-нибудь еще — не стесняйтесь и пишите.

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


  1. zag2art
    12.08.2021 19:09
    -2

    а в статье есть мат...


    1. sh3p42d Автор
      12.08.2021 19:51

      Привет! Странно, вроде все видео без звука...

      Если речь про «ебаное IT», то это название паблика :)


      1. zag2art
        13.08.2021 10:50

        так там же латиницей - это другое


  1. Dartess
    12.08.2021 20:38

    Проблемы, с которыми мы столкнулись, работая с BrowserStack:

    Это не живые устройства, а их эмуляция

    Там же Real Devices? Симуляторы (а не эмуляторы) там тоже есть, но они заныканы подальше и нужны только для совсем древних версий iOS.


    1. sh3p42d Автор
      13.08.2021 06:21

      Привет! Если там реальные устройства, тогда почему возникали ситуации, когда в BS мы видели/не видели баги или непонятную верстку, а на живом устройстве этого не было? Вот и нам было непонятно :(

      И это было не на древних устройствах и версиях, а на актуальных.


  1. z3us
    13.08.2021 02:48

    Вы сравнивали с https://github.com/zebrunner/stf ? Это DeviceFarmer (бывший openSTF), подпиленный под iOS. DeviceFarmer все никак в upstream не вольют поддержку iOS (есть и другие форки разной степени сырости). У нас уже год крутится с некоторыми модификациями без проблем, надо будет ваше решение тоже попробовать :)

    В целом AmazonDeviceFarm, headspin.io и многие другие фермы для удаленного доступа к девайсам основаны на openSTF допиленном (libpcap патчат и андроидоский хардкод меняют на iOS специфичные штуки), но свои плюшки обратно не контрибьютят :(


    1. sh3p42d Автор
      13.08.2021 06:25

      Привет! Мы достаточно ленивые (как и любые другие тестеры), поэтому сначала искали готовые решения, но на тот момент даже сырых не было, а OpenSTF ещё даже не планировал добавлять iOS.


      1. leorush
        13.08.2021 11:41

        Ну вообще в STF issue про поддержку iOS было заведено аж в 15 году, и вполне рабочее решение было уже в феврале 19 года. https://github.com/openstf/stf/issues/64#issuecomment-468213912

        А так у t-mobile тоже было что-то похожее. https://github.com/tmobile/stf_ios_support


        1. z3us
          13.08.2021 13:12

          Насколько я помню то где-то в 2018 уже прилично форков с поддержкой iOS было, просто не всем надо было (например нам) до удаленной работы. Насколько я помню 2GIS об этом где-то в 2018 рассказывал :)


      1. sh3p42d Автор
        13.08.2021 17:20
        -2

        Привет, ребята! По поводу STF:
        одно дело заявить, а другое дело, чтоб это работало) если бы это нормально работало - то окей, но это работает так себе. Во-первых. А, во-вторых, если читать тред внимательнее, то можно увидеть, что со всеми этими проблемами они и столкнулись, которые мы пробовали решить: многопоточность и доставка изображения на экран без лагов. И, в-третьих, забыл упомянуть в статье, нашу ферму мы как раз и начали писать 16 году, и пока это делали, появились какие-то форки STF. И последнее, с STF мы тоже знакомы, на ней у нас андроид ферма.