Як я покращив процес виконання автоматичних тестів на pytest, Selenium та Playwright

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

У цьому дописі хочу поділитись власним досвідом покращення процесу автоматичного тестування веб-застосунків на Python, pytest, Selenium, Playwright та як я розробив інструмент Testinel (test sentinel, вартовий за тестами). Мотивація створення цього інструменту — скорочення часу інженерів на виправлення помилок в автотестах та зниження порогу входу для автоматизаторів.

Вступ

Один з моїх улюблених коміксів XKCD це «Відмазка програмістів № 1, щоб законно байдикувати» (автор Randall Munroe):

Менеджер:

— Агов! Повертайтеся до роботи!

Програмісти:

— Код компілюється!

— А, тоді добре.

З часу публікації пройшло майже 20 років, але цей комікс досі актуальний не лише для великих проєктів на мовах, що компілюються (C++, Rust, Swift тощо), але і для процесу автоматизації тестування веб-застосунків.

— Повертайтеся до роботи!
— Тести виконуються!
— А, тоді добре.

Що робити інженеру з автоматизації тестування, доки виконуються автоматичні тести? Якщо увесь пакет тестів проходить за лічені хвилини, то можна піти заварити кави або відкинутись у кріслі та трішки відпочити. А якщо тести виконуються десятки хвилин або навіть годинами? Існує декілька варіантів:

  • нічого не робити, відпочивати;
  • нічого не робити, дивитися в консоль або сторінку CI-сервера;
  • робити щось інше: писати нові тести, спілкуватись з командою, тестувати руками.

Якщо в вас є інші варіанти, то напишіть в коментарях, що ви робите, коли цілу годину виконуються тести.

Дві проблеми контроля виконання автоматичних тестів

Тут я помітив першу проблему процесу тестування: під час виконання довгого пакету автотестів інженер неефективно витрачає свій робочий час. Він або нічого не робить (XKCD-варіант) або переключається на інші завдання, тим самим ефективність праці знижується, бо інженер втрачає контекст та контроль за виконанням тестів. Перемикання між завданнями також дає негативний ефект.

Що я розумію під контролем виконання автотестів? Якщо всі тести пройшли, що буває нерідко, то це добре — роботи у інженера буде небагато: треба буде лише звітувати менеджеру та команді, що автотести не виявили проблем. Якщо тести впали, то починається важка праця з обробки звіту:

  • виявити які тести впали;
  • для кожного впавшого тесту виявити причину падіння: помилка в веб-застосунку, помилка в тестових даних, помилка в коді автотестів чи відмова тестової інфраструктури;
  • для помилок тестів та відмов в тестовій інфраструктурі треба усунути ці помилки та перезапустити тести;
  • для помилок в веб-застосунку треба створити або перевідкрити тікет в багтрекері.

Чому ж інженер не контролює виконання тестів з самого початку? Тому що тестраннер pytest побудовано таким чином, що він формує детальний звіт з тестування після того, як пройшли усі тести (див. на відео нижче). Інженер бачить, що тест впав (FAILED), але причину падіння: виняток, повідомлення, місце у коді — цю інформацію pytest надасть лише після того, як усі тести буде виконано.

Ця проблема відчувається ще гірше на CI-сервері, тому що різні артефакти тестування: логи, скріншоти, відео тощо будуть доступні також після виконання автоматичних тестів.

Висновок № 1: інженер не має повної інформації для виявлення причини падіння під час виконання автотестів. Без цієї інформації інженер не може створити ані якісний тікет в багтрекері, ані якісно виправити скрипти автотестів.

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

  • трейсбек може бути досить великим;
  • exception message може бути досить великим;
  • місце де виникає виняток — це не те місце куди треба дивитись, бо треба дивитись в код автотестів, а не код бібліотеки;
  • усе перелічене — це довге полотно тексту.

А хто не тестує, то можете подивитись наприкінці у відео вище або приклад на скріншоті нижче. І це ще лише частина, бо звичайно трейсбек не влазить на один екран монітора.

Висновок № 2: інженер витрачає багато часу читаючи багато тексту, щоб зрозуміти, через що тест впав і як це виправити.

Як я вирішив ці дві проблеми

Нагадаю, які проблеми я вирішую:

  1. pytest не генерує детальний звіт до кінця тестування.
  2. Діагностична інформація щодо падіння тестів погано структурована.

Проблему терміновості звітності вирішив розробивши плагін pytest-testinel, який струмить події та діагностичну інформацію під час тестування на хмарний сервер, та паралельно завантажує скріншоти, відео та трейси Playwright у хмарне сховище, щоб усе це було доступне одразу як закінчується тест, а не тоді, коли закінчаться всі тести.

Переробляти, рефакторити або якось анотувати тести не треба. Це drop-in плагін, тобто, його треба лише тільки встановити та сконфігурувати, щоб він запрацював:

  1. Зареєструватись, створити проєкт та отримати TESTINEL_DSN
  2. pip install pytest-testinel
  3. export TESTINEL_DSN=https://testinel.dev/ingest/your_secret_dsn/

І все!

У цьому відео показаний струм тестових подій з Bitbucket Pipelines на хмарний сервер. Зверніть увагу, що результат тестування зʼявляється в міру проходження тестів на CI-сервері. Можна починати аналізувати падіння одразу, а не чекати доки усі тести пройдуть.

Проблему поганого структурування діагностичної інформації я вирішив гарним структуруванням діагностичної інформації:

  • дістав з повідомлень ключову інформацію, приховав зайве сміття;
  • кожен фрейм трейсбека відокремив від інших;
  • класифікував фрейми на test/page object/selenium/etc та приховав код бібліотечний фреймів, бо дивитися в них треба не так часто, як в код тестів;
  • скріншоти, відео та Playwright-трейси додав до звіту, щоб інженеру не треба було йти та шукати їх на CI-сервері або у папці зі звітами;
  • додав трішки кольору в код, щоб оченята раділи.

В результаті отримав one big beautiful™ звіт з тестування:

Як бонус отримав історію запусків автотестів. Вся структурована інформація вже була у базі даних, чому б її не показати?

Хто запускає тести за допомогою Python, pytest, Selenium та Playwright, то цю систему можна використовувати безкоштовно.

Висновки

Вже пів року я тестую це рішення з нашою командою автоматизованого тестування. Багато разів помічав, що коміти виправлення помилок в автотестах зʼявляються в гіті раніше, ніж встигають закінчитися автотести. Тому гіпотеза цінності струма подій у реальному часі підтвердилась не лише позитивними відгуками інженерів, а й на практиці. В кого є бажання протестувати на власних тестах, то можете зробити це безкоштовно: testinel.dev

«Володимире, ти запізнився на кілька років, ці стактрейси вже не читає людина. Агенту будь-яка різниця якого кольору код в трейсбеці!»

You’re absolutely right!™ Я запізнився! Ідея такої системи зʼявилась в мене ще задовго до ШІ-революції, та щоб закрити гештальт вирішив довести її до продакшену. Окрім цього, агенти не вирішують проблему струму подій у реальному часі та хмарного сховища діагностичної інформації, тому щоб Testinel був корисний я запланував розробку скіла та CLI-утіліти, яка надасть усю цю діагностичну інформацію для агентів. Тому гадаю, що цей інструмент буде корисним, за умови впровадження такої інтеграції.

Вова, завжди закривай гештальти.

👍ПодобаєтьсяСподобалось10
До обраногоВ обраному1
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

Ідея норм. Але є вже аналоги того, що Ви зробили. Аналоги породжені з selenium base. І також включають selenium, pytest, Playwright. А також Typescript та навантажувальні асинхронні фреймворки.
Також є інтеграція АІ для красивих звітів у різних форматах . І також різне налаштування нотифікацій. + Зручне апі для конектів до CI/CD .
Але Ваша розробка теж цікава. Дякую 🤝

Дякую, пошукаю, додам в перелік competitors.

Якщо в вас є інші варіанти, то напишіть в коментарях, що ви робите, коли цілу годину виконуються тести.

Працюю над іншими тасками :)

В цілому ідея класна і мені імпонує, що автор імплементував її самостійно. Тільки не зрозумів, що відштовхнуло від використання готових інструментів. Як нижче згадували, є РепортПортал (у якого RabbitMQ працює як шматок лайна, але все ж), навіть забагований Тестомат вміє в рантайм репортінг (щоправда скріншоти, логи додаються після виконання всього рану також)

Дякую за розгорнутий відгук!

Працюю над іншими тасками :)

Чи є для вас проблема з переключенням контексту?

що відштовхнуло від використання готових інструментів

Я трішки пригадую, що проблему з поганими звітами я відчував, але навіть не здогадався піти шукати чи є вже готове. Коли дізнався про ReportPortal 🇺🇦, Testomat 🇺🇦, TestDino 🇮🇳 та інших — вже було пізно, бо код вже почав писати. Вже після старту знайшлось шість комерційних продуктів, декілька open source proof-of-concepts. (Та я думаю що там якщо пошукати в категоріях testing tools на G2 їх буде десятки.)

Я хочу спробувати зробити це комерційним рішенням, та мабуть віднішуватись у діагностику та виправлення помилок саме в тестах для веба. Бо робити ще один TestRail — ні, бо вже є TestRail, Testomat, QASphere, KiwiTCMS та інші. Робити ще один Sentry — теж ні.

Ну а там подивимось, чи я галюциную, чи це дійсно вирішує чиюсь проблему з автотестами.

Шкода що pytest

Eat your own dog’s food — в нас усі тести на Python, тому і інструмент впроваджував для Python.

Поспілкувавшись з десятками автоматизаторів в моєму нетворку в LinkedIn я зрозумів, що більше використовується Playwright + TypeScript/JavaScript (хоча були поодинокі згадування C#, Java).

Я почав писати репортер для Playwright + TypeScript, але модель звітів в pytest достатньо відрізняється від моделі звітів в Playwright, щоб вважати обʼєднання цих моделей суровим рефакторингом. Я не хотів перетворювати усе це на «кружок програмування», тобто постійно щось розробляти та інтегрувати, та вирішив ось доробити інтеграцію Python, pytest, Selenium, Playwright, щоб вона стабільно працювала хоча б для моєї команди, робити умовний «реліз» (що і роблю за допомоги цієї статті, дякуючи редакції ДОУ).

Тому Playwright + TypeScript/JavaScript в шортлісті на першому місці.

Олександре, а яку інтеграцію ви хотіли би бачити?

PS Взагалі pytest крутий із коробки, а наявність сотень плагінів до нього робить його неймовірно крутим. ;) Наприклад, я пишу тести щоб тестові дані були окремо від тестів, так якийсь хлопець з Німеччини зробив такий плагін, щоб тестові дані потрапляли в тест з CSV-таблиці: https://first.institute/blog/vidokremyty-dani-vid-kodu-testuvannya-z-csv-pytest/

«Проблему поганого структурування діагностичної інформації я вирішив гарним структуруванням діагностичної інформації»

:)

;)

Радий, що цей pun хоч хтось побачив. Усю статтю писав заради нього. :)

У цьому каламбурі і є візія Testinel — зібрати якомога більше діагностичної інформації, щоб помилки було простіше виправляти. :)

Та не обв’язково ж чекати виконання всіх тестів. Мона створити фікстуру, яка буде робити пост запит до іксрею, тестрейлу і апдейтити конкретний тест.

Так, це можна зробити фікстурою. Але в Testinel воно трішки складніше, зроблено на хуках. Воно ловить виключення не лише у call фазі, а також у setup та teardown. Окрім цього, робиться інструментація (патч Selenium), створюється окремий потік для завантаження артефактів: скріншотів, трейсів, щоб не блокувати виконання тестів.

Якщо в вас воно працює на однієї фікстурі, то я б залюбки запитав у вас демо реалізації. Дякую.

Btw, агент з відкритим кодом (а яким ще може бути пакет у Пайтоні?), можна подивитись, що він робить: github.com/Testinel/pytest-testinel

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

В нас також є тестрейл. Чому я вирішив це робити без нього:

1. У Тестрейла спеціалізація на менеджменті тест-кейсів. В Testinel фокус на падіння в автоматичному тесті, та пошуку причин падіння.

2. Тестрейл курва дорогий! $38 per seat / month, що на команду з 5 інженерів дає 190$/місяць просто за базу даних тестів — я вважаю, що це дуже дорого. Так, я на розробку Testinel витратив багато часу, але з точки зору споживача тарифікація йде пропорційно споживанню — кількості тестів, які обробляються системою: спробувати можна безкоштовно, до 10000 тестів — 29$/місяць, до 50000 тестів — $89/місяць. На платних планах користувачі та проєкти майже необмежені, тому що додаткові користувачі вони не споживають ресурсів. Ціни та ліміти в планах зараз умовні, бо це ще гіпотеза, що саме так воно повинно бути.

3. В Тестрейлі я не побачив нормального інтерфейсу для аналізу помилок: щоб була присутня діагностична інформація. Тобто просто текст трейсбека я можу подивитись і в pytest-html-report.

4. Ну і not invented here — хотів власними руками зробити інструмент від початку і до кінця. :) Не буду брехати, що мені не було просто цікаво це робити.

Ви зробили Report Portal на мінімалках ))

Є таке. :) Але у нього є недолік: Not Invented Here. :)

Не зміг пройти повз. Привіт Вова. Привіт Ярик. Який же тісний світ:)

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