Скорочуємо час виконання UI-тестів з використанням Selenium Grid у Minikube-кластері
Привіт. Я Євгеній Овчаренко, працюю QA Automation Lead у Master of Code Global. Маю 4 роки досвіду як мануального, так і автоматизованого тестування. Зараз займаюся розробкою автоматизованих тестів з використанням різних платформ і фреймворків Java (Selenide, Selenium, REST Assured, JUnit) і Node.js (Jest).
У статті, спираючись на власний досвід, я розповім про проблему великої тривалості виконання UI-тестів, поділюся інформацією про Selenium Grid і Minikube та як з їхньою допомогою можна вирішити проблему, перевагами і недоліками запропонованого підходу.
Матеріал буде корисним:
- QA Automation-інженерам (для скорочення часу виконання тестів);
- розробникам (для самостійної реалізації цього процесу, за відсутності QA-інженера в команді);
- менеджерам проєктів і продакт-оунерам — для розуміння того, як цей підхід може заощадити час і кошти).
Selenium Grid cluster
Дослідження теми я почав, коли зіткнувся з тим, що послідовне виконання тестів в одному потоці для одного браузера займає в середньому 40 хвилин. А під час крос-браузерного тестування кожен додатковий браузер потребує такої самої кількості часу. Шукаючи шляхи оптимізації цього процесу, я зупинився на Selenium Grid-кластері.
Selenium Grid-кластер має два основні компоненти: hub i nodes.
Hub — сервер, який приймає запити на доступ від клієнта WebDriver і направляє тестові команди JSON на віддалені диски на nodes. Він проводить одночасне виконання тестів на декількох машинах, централізовано керуючи різними браузерами, що полегшує аналіз і порівняння результатів.
Node — віддалений пристрій, який складається з рідної ОС та віддаленого WebDriver. Він отримує запити від Hub у вигляді тестових команд JSON і виконує їх за допомогою WebDriver.
Архітектура Selenium Grid
Пропоную розглянути результати виконання smoke-тестів, використовуючи підхід Selenium Grid:
- Виконання тестів в одному потоці для одного браузера почергово займає в мене 9 хвилин 25 секунд, а на двох — 18 хвилин 55 секунд.
- Для пришвидшення виконання тестів запускаю їх у двох браузерах паралельно, використовуючи Selenium Grid підхід (тобто на виконання двох потоків іде 9:25 хвилин 25 секунд, а не 18 хвилин 55 секунд, як у попередньому варіанті).
Утім, проблема із виконанням тестів в одному потоці для кожного браузера лишилася, і я шукав способи її розв’язання.
Minikube cluster
Найважливішим в ухваленні рішення на користь Selenium Grid у Minikube-кластері стало те, що він зручний у налаштуванні, не потребує додаткової підтримки, безплатний.
Він має два типи ресурсів: Master i Node.
Master управляє кластером: запуском застосунків, їхнім плануванням, підтримкою й оновленнями. Master містить такі типи ресурсів:
- Controller manager — стежить за загальним станом кластера через API server і вносить зміни, щоб перевести поточний стан у необхідний.
- Scheduler — це частина платформи Kubernetes, що спостерігає за новоствореними подами, яким не призначено node. Він відповідальний за пошук найкращого вузла, на якому буде запущений pod.
- API server.
Node — це віртуальна машина, або фізичний комп’ютер, що виконує функцію робочої станції в кластері Kubernetes. Вона має утиліту Kubelet — агента управління нодою та спілкування з Kubernetes-майстром через API server, а також Docker-інструменти обробки операцій з контейнерами:
- Kubernetes Pod — група контейнерів, розгорнутих на одному хості.
- ServiceProxy — сервер для доступу до hub.
- Kubelet — відповідає за підтримку pods і працює з PodSpec.
- PodSpec — це специфікація, що описує поведінку pod в YAML- або JSON-файлах.
Архітектура Minikube
Результати виконання тестів
Розуміючи, що таке Minikube, розглянемо результати виконання тестів з використанням Selenium Grid у Minikube-кластері.
З підходом Selenium Grid у Minikube-кластері запускаю тест у три потоки для одного пулу з’єднань браузера Firefox, масштабованого до трьох у Minikube-кластері. Таку саму конфігурацію застосовую до Chrome. З таким підходом виконання сотні тест-кейсів на обох браузерах (по п’ятдесят на кожен) займає 5 хвилин 28 секунд. Цим ми скоротили час виконання тестів на 14 хвилин.
Щоб більше мінімізувати час, можна збільшити потоки виконання тестів і масштабувати браузери. Але важливо враховувати ресурси вашої локальної машини.
Тож використання підходу Selenium Grid у Minikube-кластері заощадило 72% часу. Якщо треба запустити більшу кількість тестів, ресурси, витрачені на налаштування інфраструктури й написання коду, компенсуються. Справа за часом: на проєктах з активною фазою розробки й постійними деплоями це відбудеться швидше, а в інших — повільніше, залежно від кількості запуску тестів.
Плюси та мінуси
Для мене перевагами підходу є:
- Відсутність додаткових витрат та обслуговування.
- Легке встановлення на локальну машину, швидке налаштування й оновлення.
- Наявність змістовної бази інструкцій.
- Можливість легко мігрувати на Kubernetes-кластер до хмарних обчислень у разі браку ресурсів локальної машини.
- Зручний Dashboard для моніторингу й перегляду логів і масштабування браузерів.
- Self-healing-підтримка, що дає змогу автоматично перезапускати контейнери, якщо вони з якоїсь причини стали недоступні.
- Усунення проблем із затримкою передачі інформації між сервісами в кластері завдяки тому, що сервіси перебувають в одній мережі.
- Масштабоване рішення.
Серед недоліків можу виокремити:
- Відмовостійкість. Якщо локальна машина, на якій запущено Minikube з налаштованим Selenium Grid, недоступна, то доступу не буде й до всього кластера.
- Hub доступний лише в одному екземплярі й не масштабується. Тому якщо він стане тимчасово недоступним, тести, відправлені клієнтом, і тести, запущені на інших вузлах, будуть фейлитися. Та завдяки self-healing capability за певний час доступ до хаба може відновитися.
- Відсутність можливості встановлення балансувальника запитів і створення кількох Selenium Grid кластерів. Адже вся інформація про Browser Nodes і сесії зберігається в пам’яті конкретної Node й не поширюється між ними.
Як налаштувати Selenium Grid у Minikube-кластері
Щоб почати використання Selenium Grid у Minikube-кластері, треба встановити Minikube й VirtualBox, завантажити деплойменти і YAML-файли, а далі за кроками:
0. Перед стартом Minikube-кластера необхідно збільшити ресурси VirtualBox.
Це важливо, адже Minikube запускається із використанням конфігурації за замовчуванням: Creating VirtualBox VM (CPUs = 2, Memory = 2048 MB, Disk = 20 000 MB). Якщо ресурси не збільшити, виникнуть проблеми з масштабуванням браузерів і запуском тестів на них у потрібній кількості. Тести не запустяться на жодному з вузлів, адже виділеної пам’яті бракує для запуску всіх масштабованих вузлів.
Конфігурація віртуальної машини, на якій я запускаю Minikube-кластер
1. Minikube start.
2. Необхідно створити деплойменти сервісів. У цьому разі ми створимо деплойменти hub, proxy-service, firefox-node й chrome-node браузерів, виконуючи такі команди:
kubectl create --filename=<path>/selenium-hub-deployment.yaml kubectl create --filename=<path>/selenium-hub-svc.yaml kubectl create --filename=<path>/selenium-node-chrome-deployment.yaml kubectl create --filename=<path>/selenium/selenium-node-firefox-deployment.yaml
3. Після того як ми створимо деплойменти, нам потрібно надати доступ до hub через наш розгорнутий proxy-service, виконуючи команду:
kubectl expose deployment selenium-hub --type=NodePort
4. Далі, залежно від тих ресурсів, що було виділено для Minikube-кластера, ми масштабуємо браузери в кластері (у цьому разі це по 5 реплік):
kubectl scale deployment selenium-node-chrome --replicas=5 kubectl scale deployment selenium-node-firefox --replicas=5
5. Наступною командою отримуємо UrlHub для надсилання інформації про тест з клієнта
minikube service selenium-hub --url
6. Виконавши команду Minikube Dashboard, автоматично відкриється Kubernetes Dashboard, на якому можна подивитися статус усіх pods і кількість розгорнутих деплойментів.
7. Minikube dashboard:
8. Готово до використання.
Після того як ми налаштували Selenium Grid у Minikube, зробили відповідні масштабування браузерів і написали код, можемо запускати тести. У цілому, це залежить від того, де ви запускатимете код: це може бути як локально, так і через Jenkins.
Наприклад, цей підхід я запускав за допомогою Jenkins, бо він має інтеграцію з Maven, а проєкт з тестами написано на Java з використанням Maven. Відповідно, усе, що мені потрібно було зробити, — встановити Maven Integration-плагін у Jenkins і налаштувати Jenkins Job для запуску тестів з GitHub.
Підхід з використанням платформи Node.js для цієї платформи я не застосовував. Проте думаю, що проблем з його налаштуванням не виникне.
І наостанок посилання, яке раджу вам переглянути перед запуском цього підходу:
- Kubernetes.io — офіційний ресурс для кращого розуміння концепцій і детальнішого ознайомлення із сервісами.
- Рецепти Selenium Grid (з YAML-файлами й докладним описом Readme.md).