Як відстежувати і мінімізувати кількість flaky-тестів на продукті
Привіт! Мене звати Олексій Лакович, я займаюся автоматизацією тестування та процесів вже понад 10 років. Працюю Head of Quality в українській продуктовій компанії Solidgate, де ми будуємо фінтех-екосистему, яка дозволяє клієнтам швидко та безпечно приймати оплати по всьому світу.
Тести, які «флачать» — постійна проблема, яка може віднімати багато часу та нервів. В цій статті розповім про досвід нашої команди з відстеження та мінімізації flaky-тестів.
Нестабільні тести і де їх шукати
Всі команди, які мають автотести, так чи інакше стикаються з нестабільністю їх виконання. Вони як вогники на новорічній ялинці — загоряються то червоним, то зеленим. В чому їх підступність? В кращому випадку перевірка тестів, що іноді падають, займає додатковий час, а це затягує реліз. Коли розробник або тестувальник бачить, що набір тестів показує результат проходження на 98% (а не 100%), іде розбиратися — що ж трапилось із тими 2%.
В гіршому випадку, якщо такі умовні 2% тестів, що впали, з’являються регулярно, то з часом всі будуть їх ігнорувати і виходити в продакшн з тими результатами, що є. Ймовірніше, ніхто навіть не буде розбиратися, що саме падає і з якої причини. В певний момент, коли тест дійсно показує помилку, на нього вже ніхто не зверне увагу, бо тестам перестануть довіряти. Один цей факт може знецінити всю автоматизацію, яку в компанії будували роками, наймали фахівців, витрачали гроші і час.
Причин, чому з’являються flaky-тести, може бути декілька:
- певна «нерегулярна» проблема з продуктом (або одним з оточень). Тобто продукт періодично працює некоректно, і це відображається в тестах;
- самі тести. У більшості випадків причиною нестабільності тестів стають недоліки при їх написанні. В них можуть бути неправильно задані очікування (тест має чекати на конкретну подію) або неправильно визначена власне подія. Чим досвідченіший автоматизатор, тим чіткіше він може відрегулювати ці параметри та мінімізувати нестабільність тестів.
Нижче розповім детальніше, як ми організували боротьбу з flaky-тестами.
Які тести вважати як flaky
Перше, що ми зробили — визначили для себе, які тести вважати як flaky.
Друге — додали старий добрий механізм перепроходження тестів, що впали (Rerun), відмічали результати кожного тесту, який був перезапущений, спеціальним прапорцем (isRerun), та надсилали цю інформацію в БД. Тобто для нас flaky-тест — це тест, який пройшов успішно після перезапуску (isRerun=true + result=success).
❗️ Важливо: іноді команди вирішують піти іншим шляхом — фіксувати результати тестів в межах різних прогонів. Прогони можуть мати різницю в декілька годин і, відповідно, оточення, на яких проганяються тести, ймовірно, може знаходитись у різних станах. Такий підхід може давати невалідні результати.
❗️ Важливо: не додавайте Rerun окремо, без регулярного аналізу результатів тестів. Інакше ви можете пропускати нестабільності в продукті та суттєво збільшити час проходження наборів тестів. Також не варто додавати Rerun в ваші хелсчеки (Uptime тести/Моніторінг продукту).
Збір даних
Намагатися спіймати flaky-тести за один прогон — неефективно. Продукт, оточення або ваш тест може бути в конкретний момент неробочий з різних причин. Аби зробити релевантні висновки про кількість нестабільних тестів, ми збираємо всі дані про результати тестів, а потім аналізуємо за певний період часу або за певну кількість запусків. До прикладу, якщо на десяти прогонах флачить один і той самий тест — це вже патерн, в якому достатньо даних для того, щоби робити висновки.
Ці показники дають можливість побачити те, що треба фіксити в першу чергу, і допомагають встановити пріоритетність цілей, яких треба досягти найближчим часом.
В нашій практиці ми записуємо інформацію про всі результати тестів в окрему базу даних (ми обрали Elasticsearch). Фіксуємо тести, їх атрибути, результат, а також зазначаємо, в рамках якого набору тестів та на якому оточенні був прогон.
Далі ці дані варто візуалізувати. Це можна робити, просто створюючи запит в саму базу, але для більшої зручності використовують дашборди, наприклад, в Grafana. Також ця інформація є корисною для інших метрик, які можуть вас зацікавити (кількість тестів на кожного автоматизатора в команді, час виконання тестів, відсоток успіху ваших наборів тестів тощо).
Збір результатів тестів в базу та варіації використання цих даних заслуговує окремої статті. (Якщо ця набере багато коментарів та лайків, так і зробимо).
❗️ Важливо: звісно, можна це робити вручну — фіксувати десь кожний запуск, виписувати тести, що повторюються. Але у такому випадку неможливо відстежувати тренди в режимі реального часу, і буде важко порівнювати метрики з показниками за минулий місяць, три місяці тощо. Найкраще — автоматизувати цей процес, щоби це не була разова практика.
Аналіз метрик і робота з ними
В межах роботи з flaky ми зазвичай відстежуємо декілька речей, за якими будуються графіки і таблиці. Перша — середня кількість flaky-тестів у конкретному наборі. Наприклад, за нашими даними ми можемо одразу побачити, що сьют по конвертації валют проходить успішно, а по пеймент-формі — не завжди, іноді падають декілька тестів по трекінгу подій. Відповідно, в цьому випадку нас не буде цікавити конвертація валют, а от сьют «Платіжна форма» ми будемо фіксити в першу чергу.
Навіщо це взагалі потрібно? Певна частина функціональності змінюється частіше за іншу — тобто її частіше допрацьовують, вносять нові фічі тощо. Якщо у вас є набір тестів, який проганяли всього раз на місяць і він «флачить», немає сенсу ним займатися, тому що наступного разу він проганятиметься лише за місяць.
Це не так ефективно, як пофіксити ті тести, які проганяються частіше. Адже, якщо в наборі, який проганяється щодня, є нестабільні тести, то хтось чекає, поки рерани ваших тестів пройдуть успішно.
Друге — ми слідкуємо за топом тестів, які флачать частіше ніж інші. Це або погано написані тести, або регулярна проблема продукту. Складаємо список тестів: від того, що найчастіше «флачив», до того, що найрідше. Далі першочергово фіксимо ті тести, що найчастіше флачать (та запускаються).
Інша опція — можна першими фіксити ті тести, які довго виконуються. Вони можуть запускатися раз на тиждень, але виконуються близько 10 секунд. А є тести, які «флачать», але виконуються за секунду. Тут важливо визначити, що є пріоритетом у вашому конкретному випадку.
По-третє — відсоток flaky-тестів від загальної кількості всіх тестових результатів регресії. Це такий собі показник здоровʼя автоматизації проєкту. Чим нижче показник, тим краще настрій у AQA.
Четверте — час (сума часу) прогону усіх flaky-тестів регресії (на скриншоті показник за 90 днів). Це у поєднанні з попередніми метриками дає розуміння, як сильно нестабільні тести впливають на час, який витрачає ваша команда при проведенні релізів.
Насправді найголовніше — це кінцева мета, ви маєте її чітко зафіксувати. Можливо, ваша ціль — пофіксити конкретний набір тестів, загалом зменшити відсоток нестабільних тестів, або є завдання зануритись у продукт і виявити аномальні місця. Зважаючи на це, далі можна вирішувати: чи фіксити найкритичніші проблеми з точки зору функціональності, чи обирати ті тести, що найчастіше запускаються. В нашому випадку основною метою було скорочення часу, який займає перепроходження тестів, та мінімізація потенційних аномалій, які можуть відчувати клієнти.
Технічна реалізація
Неважливо, яка у вас мова програмування або який тестовий фреймворк. Ви можете реалізувати це на будь-якому стеку технологій.
Я дам коротку інструкцію для стека Java + TestNG:
- Провести реран тестів за допомогою IRetryAnalyzer.
- Імплементувати IAnnotationTransformer для простішого підключення ретраю (Через Listener в xml, а не для кожного тесту окремо).
- Завести задачу на DevOps для сетапу БД www.elastic.co (або вручну).
- Взяти готовий клієнт для роботи з Elasticsearch (або зробити свій).
- Реалізувати ITestListener, який буде записувати дані результатів ваших тестів (ви самі можете обирати, які атрибути ви хочете додавати), та пушити їх в Elastic (дані краще збирати на рівні лісенеру тестів, а відправляти їх в БД разом на завершенні всього набору).
- Таску на DevOps для сетапу grafana.com (або вручну).
- Налаштувати Графік або будь-який інший візуал ваших даних в Grafana.
- Радіти, пишатись, розвиватись:)
Коли щось іде не так
Як у будь-якому процесі, ви можете зіткнутися з проблемами. Ми не стали винятком, і допустили багу в маркуванні Rerun-тестів. На початку ми відмічали всі тести як flaky, окрім самих flaky (isRerun + success), і тому певний час спиралися на некоректні дані та намагалися протягом одного дня розбирати робочі тести. Варто ретельно перевіряти зміни в вашому проєкті(ах) автоматизації — так, як і в продукті.
Також доволі розповсюджена складність — коли виникає певна проблема з продуктом, яку не знають, як вирішувати. До прикладу, завантаження сторінки: вона то швидко завантажується, то довго, або запит довго повертає результат, або транзакція міняє статус тощо. Це така химерна проблема, яку важко спіймати. В таких випадках треба дійти згоди з командою, що ви будете фіксити, а що — ні.
Наприклад, якщо тест очікує якусь подію протягом 20 секунд, а вона не відбувається, то вам треба домовитись, що якщо час очікування сягне хвилини, лише тоді ви будете це фіксити. Дуже важливо про такі речі комунікувати і знаходити стандарти якості вашого продукту.
Мінімізуємо появу нестабільних тестів: чек-лист нашої команди
Навіть якщо ви дотримуєтесь усіх правил, в кожному окремому випадку можуть з’явитися нюанси. Суть не в тому, щоб унеможливити появу нестабільних тестів взагалі, а в тому, щоб контролювати їх кількість та причини виникнення.
Усім дякую за увагу!
P.S. Не тредсліпте на своєму ранчо 🤠, а також донатьте на ЗСУ за допомогою нашої платіжної форми)
3 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів