Як тестувати нативні застосунки: використання емуляторів та огляд інших підходів

💡 Усі статті, обговорення, новини про тестування — в одному місці. Приєднуйтесь до QA спільноти!

Вітаю, мене звати Євген, я працюю Java Automation QA Engineer в продуктовій ІТ-компанії Quarks. Компанія в цілому спеціалізується на створенні продуктів та технологій у сфері Social Discovery, і мій проєкт Kismia пов’язаний саме з цією предметною областю.

У цій статті я поділюся досвідом команди, як організувати функціональне тестування нативних застосунків, плюсами та мінусами різних підходів, а також поясню, як ми побудували власну інфраструктуру емуляторів девайсів та що з цього вийшло.

Трохи контексту

Наш продукт охоплює вебверсії (десктоп та мобільні пристрої) та нативні застосунки для Android та iOS. Для кожного з цих напрямів створені кросфункціональні команди, до яких входять і мануальні тестувальники. Команда Automation складається з трьох інженерів, які не є частиною продуктових напрямів. Вони відповідають за підтримку і розвиток автоматизації під всі платформи та загальну координацію QA-процесів у компанії.

Я приєднався до компанії у січні 2020 року і потрапив на своєрідну зміну поколінь. Так сталося, що частина Automation Team залишила проєкт з особистих причин. Тож довелося запросити в команду ще двох інженерів для підтримки наявного фреймворку автоматизації. Паралельно вирішили переходити на новий стек технологій для автоматизації, який би надав можливість масштабувати і стабілізувати тести.

На той час існувала тільки вебверсія продукту. Під нього був створений проєкт автоматизації, який був доволі класичним поєднанням Java + Selenide + Maven + TestNG. Для безперервної інтеграції використовувався Jenkins, який підіймав Docker-контейнер з Chrome.

До речі, цей проєкт надалі був об’єднаний у монорепозиторій з використанням Spring 5 та Gradle, але це вже трохи інша, хоча теж цікава історія.

Тоді ж компанія почала розробку нативного застосунку. Виходячи з того, що перша версія під Android очікувалася вже влітку 2020-го, у команди було завдання організувати процес автоматизованого тестування під нову платформу.

Автоматизація під нативні застосунки

Зважаючи на те, що вся автоматизація під веб була побудована за допомогою Java, і саме ця мова програмування була основною для всіх у команді автоматизації, вирішили вибрати зв’язку Java + Appium.

Зроблю невелику ремарку й одразу відповім на запитання: «А чому не використовувати нативну мову на кшталт Kotlin, Swift?», «Чому обрали саме Appium, а не щось інше (наприклад, той же Espresso)?».

Так, я розумію, що використання нативних рішень має низку переваг, але зважте на наступні фактори:

  1. Для всіх членів команди автоматизації Java була основною мовою програмування.
  2. Ніхто з інженерів до того не мав досвіду в автоматизації тестування нативних застосунків, і навантажувати команду новою мовою програмування на додачу до нового стеку технологій було ризикованим рішенням.
  3. На Java вже була написана велика кількість системних тестів (e2e) для вебу. Незабаром мала стартувати розробка iOS-застосунку, й основна ідея полягала в уніфікації стека технологій під всі платформи.
  4. Appium — поширене open source рішення, яке працює і під Android, і під iOS. Воно безкоштовне (що теж є вагомим плюсом) і має велике розвинуте комʼюніті.

Звісно, ідеально було б виділити під нову платформу окремого інженера, який би розвивав нативні підходи, але зважте перелічені фактори, невеликий розмір команди та потенційну появу ще й iOS-застосунку (зі своєю нативною екосистемою). Тому ми обрали курс на взаємозамінність та уніфікацію технологій для різних платформ.

Реальний пристрій чи емулятор

Як організувати функціональне тестування для нативних застосунків? Якщо під веб у нас є лише одна опція — це браузер (єдина різниця в тому, де його запускати — локально, тестовий сервер, контейнер), то для нативних застосунків потрібен пристрій, на який він буде встановлений. То як це має виглядати у нас? Ми доволі довго радилися всередині команди та розглядали кілька опцій.

Опція 1. Організувати парк девайсів всередині компанії.

Ідея: виділити сервер, до якого будуть фізично приєднані мобільні пристрої. Він розподіляє навантаження, контролює встановлення застосунку на пристрій та виконання тестів.

Плюси: рішення легко реалізується з технічної точки зору, після придбання обладнання не потребує фінансових витрат. Пристрої легко контролювати та усувати проблеми. Рішення працює всередині компанії, тому немає проблем з безпекою.

Мінуси: придбання обладнання та пристроїв потребує додаткових витрат. Попри технічну простоту необхідно виділити час на підтримку роботи пристроїв, апгрейд/ даунгрейд нових версій операційних систем. Для iOS потрібен окремий сервер на базі MacOS. З виходом нових девайсів парк пристроїв потребуватиме оновлення.

Резюме: цей варіант відкинутий через його неелегантність та громіздкість. Але цілком має право на існування.

Опція 2. Безкоштовні хмарні ферми пристроїв

Ідея: безкоштовні сервіси, які дають змогу підключатися до різних девайсів і виконувати запуски тестів на них.

Плюси: рішення безкоштовне. Не потребує контролю девайсів та ресурсів компанії.

Мінуси: обмежена послуга сапорта у разі потреби, ненадійність, питання до безпеки використання таких сервісів, дебагу проблем при виконанні тестів.

Резюме: непоганий варіант для стартапу чи проєкту з лімітованими ресурсами, який не дуже переймається питаннями надійності та безпеки. Цей варіант не підійшов нам.

Опція 3. Платні хмарні рішення з доступом до реальних девайсів

Ідея: платні хмарні сервіси (наприклад, AWS Device Farm), з допомогою яких можна виконувати тестування на реальних девайсах на віддалених серверах та дебажити проблеми.

Плюси: не потребує контролю девайсів та ресурсів компанії. Повноцінний сапорт, надійність та закриття питання безпеки. Дебагери та додаткові тулзи для полегшення роботи.

Мінуси: платне рішення.

Резюме: хороший варіант. Єдиний недолік — зазвичай оплата здійснюється за час та ресурс використання. Виходячи з процесів розробки, за день виконується чимало тестових запусків. Рішення може бути фінансово обтяжливим для компанії.

Опція 4. Платні хмарні рішення з доступом до емуляторів

Ідея: платні хмарні сервіси (наприклад, Browserstack), які дають виконувати тести на емуляторах девайсів на віддалених серверах.

Плюси: подібні до попередньої опції. З додаткових — можна швидше та гнучкіше змінювати та кастомізувати емулятор.

Мінуси: платне рішення. З’являється проблема різної поведінки на реальному девайсі та емуляторі.

Резюме: також хороший варіант. Недолік такий самий, як і в попередньому пункті — оплата за час під навантаженням.

Опція 5. Побудова структури, що базується на емуляторах девайсів

Ідея: основна ціль — віртуалізація мобільного пристрою на власній інфраструктурі без додаткових витрат фінансових ресурсів. Підіймається фізичний сервер всередині мережі компанії. На нього встановлюється хаб, який керує створенням контейнерезованих емуляторів мобільних пристроїв (використовуючи віртуальні ноди) та проксуванням запитів до них. Перед хабом встановлений балансувальник навантаження, який керує розподіленням потоків, а на кожній ноді розгортається контейнер з відповідним емулятором девайсу.

Для iOS ідея схожа: хаб проксує запити до сервера (в нашому випадку Mac mini), який керує симуляторами пристроїв.

Плюси: рішення потребує відчутно менших фінансових витрат при старті, а надалі — умовно безкоштовне. Досить гнучке, не потребує підтримки кількох девайсів. Легка зміна конфігурації девайсів. Легкий процес дебагу. Єдиний підхід.

Мінуси: можлива різна поведінка на реальному девайсі та емуляторі.

Резюме: цей варіант видався нам оптимальним, тому ми реалізували саме його.

Як це виглядає у нас

Ми взяли за основу архітектуру, яка побудована на базі докерезації та хаба (менеджера контейнерів). Це розв’язує важливу проблему: тестувальнику не потрібно втручатися в роботу інфраструктури. Хаб виконує запуск, повторне створення, контроль стану контейнера та регулює його видалення.

Технологіями, що використовуються на проєкті є: Java + Spring + Selenide.

У ролі СІ виступає Jenkins. Підіймається докер-контейнер, на якому збирається тестовий проєкт. Далі йде запит до open source рішення від Aerokube — Go Grid Router. Це балансувальник навантаження, задача якого — розподіляти запити до сервера на основі іншого продукту від цієї ж компанії — Selenoid. Таких хабів може бути декілька, що дозволяє масштабувати рішення.

На нодах сервера розгортаються контейнери, які містять Appium Server (контролює роботу з нативною iOS), ADB (Android Debug Bridge) та емулятор пристрою, на якому і виконуються перевірки. Якщо є потреба оновити версію мобільної операційної системи чи модель емулятора девайса, це виконується швидко і не потребує багато часу, потрібно просто перезібрати образ з потрібними параметрами.

Схема для iOS — подібна. Відмінність у тому, що платформою для запусків віртуальних пристроїв є Mac mini, на якому встановлений Xcode (симулятори девайсів на iOS) та Appium Server. Виконання тестів контролює Selenium Grid 4, збалансовуючи версії симуляторів та інші бажані властивості проєктів між різними нодами в заданій кількості.

Тут може виникнути питання: навіщо використовувати два рішення — Selenoid та Selenium Grid, а не взяти за основу одне з них? На жаль, попри всі переваги Selenoid не вміє проксувати запити до iOS. Ми сподіваємося, що це буде реалізовано в наступних версіях продукту. Після цього є бажання уніфікувати стек технологій.

Чому Appium Server? Перш за все, він одночасно підтримує як iOS, так і Android. Також важливим фактором є відсутність оплат та сильне ком’юніті. Порівняльна інформація щодо Appium та інших рішень в таблиці нижче.

Отже, підходи, описані в нашому випадку, досить надійно працюють у нас вже понад рік. За цей час ми не стикалися з відмінністю в поведінці системи між емулятором та реальним пристроєм.

Звісно, можна користуватися будь-яким з описаних вище варіантів або якимось іншим. Мета статті — не переконати діяти саме нашим шляхом. Це історія нашого аналізу та вибору і, сподіваюсь, вона буде корисною тим, хто планує запровадити процес автоматизації тестування нативних застосунків у себе в компанії.

Дякую за увагу.

👍ПодобаєтьсяСподобалось22
До обраногоВ обраному8
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Класна стаття. Дякую. Але хотілось би почуть більш технічні аспекти запуска ІОС тестів по такому шляху. Або десь про це почитать якщо є де.

Вітаю, дякую за позитивний відгук.

Так ваше питання дуже доречне. Цікаво, але матеріалів по тематиці автоматизованого тестування для iOs взвгалі не дуже багато (порівнняно з веб і навіть з Андроїдом).
Більш того майже всі вони пов’язані з використанням нативних можливостей XCode та Swift. Це насправді має сенc, бо як ви знаєте екосистема Apple досить закрита для зовнішнього використання.
Ще частина матеріалів пов’язана з запуском на реальному девайсі приєдномному до MacOs пристрою. По роботі зі зв’язкою сімулятор — мова программування інфи мінімум.

Але насправді все не так важко як здається. В основі лежить сервер (все той же пристрій на MacOs — найкращий варіант MacMini), на ньому встановлений XCode та Appium (або інший тул).
В XCode створюємо потрібні сімулятори і в ідеалі, якщо запусти код, все повинно працювати. Навіть Jenkins повинен бачити таке рішення, якщо додати MacMini як його ноду.

Більш складним кейсом є прикрутити до всього цього якесь рішення для маштабування та балансування навантаження (в разі багатопоточного запуску). Варінтів тут не дуже багато — ми вибрали Selenium Grid 4
Тут вже потрібно погратися з налаштуванням всієї цієї історіі — накраще джерело інфи, офіційна документація Selenium Grid.

Ну і прикрути докерезацію, якщо вона потрібна — можно збирати тестовий код і на ноді MacMini, але буде постійно віджерати частину ресурсів.

Фінальна зв’язка — Дженкінс — збірка вашого коду — грід- аппіум- сімулятор

Жека це дійсно ти? Класна стаття, структуровано, як я вчив ;)

Підписатись на коментарі