Hot Positions, Cool Company! NeoGames
×Закрыть

Playwright — запускаємо тести одночасно for fun

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Привіт друзі! Нещодавно відкрив для себе новий інструмент для автоматизації тестування — Playwright. Точніше, читав про нього ще весною, але тоді він був ще сирий та працював тільки з JS. Зараз же повністю підтримується і для мови Python (моя основна мова програмування, наразі), що і змусило мене спробувати написати кілька тестів.

Ну я і спробував. А потім ще. А потім зробив невеликий проєкт на pytest — Супер! Страждань набагато менше, ніж зазвичай при роботі з Selenium. А ще круті фічі типу перехоплення мережевих запитів

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

«Синхронний варіант простіший» — подумав я. Менше коду, краща читабельність. «Напевне, асинхронний варіант мені ніколи не знадобиться. Така собі крута фіча, про яку всі говорять, але не використовують»...

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

І моя ж перша думка — чому б не зробити не дуже практичний, але дуже наглядний тест, знаю я один інструмент, що вміє в асинхронні операції ;) А ще не буде потреби робити OAuth 2.0 авторизацію.

Disclaimer. Я в курсі, що можна зробити крутий та ефективний тест навантаження за допомоги того ж JMeter, але то буде не так весело.

Для початку треба встановити playwright. Робив це за документацією (посилання вище).

Отже, для початку напишемо тест, а точніше 3 тести в одному:

  • Зайти на сайт
  • перейти на одну з трьох сторінок через меню навігації
  • перевірити назву сторінки
В оригіналі тест логінився унікальним користувачем в кожному потоці, але для того, щоб ви мали змогу скопіювати та запустити — я спростив його.
import asyncio
from playwright import async_playwright
from playwright.browser import Browser
import random

BASE_URL = 'https://qamania.org/'
PAGES = (('Home', 'QA Mania'), ('Blog', 'Blog'), ('Useful links', 'Useful links'))


# тут можна передати логін/пароль
async def open_test(browser: Browser, data: tuple, id: int):
   print(f'start #{id} thread')
   context = await browser.newContext()
   page = await context.newPage()
   await page.goto(BASE_URL)
   await page.click(f'text={data[0]}')
   title = await page.title()
   result = 'ok' if data[1] in title else 'not ok'
   print(f'Thread #{id}: result for page {data[0]} --> {result}')
   await page.close()
   await context.close()

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

Тепер зробимо головну функцію, що буде запускати playwright (важливо, щоб він запускався лише 1 раз). Створюємо браузер, вказавши headless=False, щоб бачити процес виконання, та масив для задач, що будуть виконуватись одночасно. Масив заповнюємо викликом функції open_test. Якщо викликати її без аргументу await, то повернеться асинхронна задача, що має бути виконана.
Далі передаємо масив задач у функцію asyncio.gather, що, згідно документації, використовується для одночасного виконання. Не пропустіть, що масив треба передати з *, оскільки функція gather приймає *args

І відразу ж останній крок — сказати модулю asyncio виконати головну функцію. Все готово.

async def main():
   print('start main')
   async with async_playwright() as p:
       browser = await p.chromium.launch(headless=False)
       tasks = list()
       for thread in range(10):
           tasks.append(open_test(browser, random.choice(PAGES), thread))
       await asyncio.gather(*tasks)
       await browser.close()


asyncio.run(main())

Запускаємо і бачимо наступну красу:

Все працює! ОДНОЧАСНО! Сам не знаю чому, але мені дуже подобається, як це виглядає.

Також під час виконання стало цікаво, скільки ресурсів потребує такий тест?
Коли відкривається 1 сторінка браузеру Chromium, вона з’їдає 25-30 МБ оперативної пам’яті, Firefox — 30-50 МБ. Тож не треба розраховувати на проведення тестування навантаження таким чином.

Власне, це все, чим я хотів поділитись . Було цікаво?

👍НравитсяПонравилось0
В избранноеВ избранном0
Подписаться на тему «тестирование»
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
Не пройшло і місяця, постає переді мною цікаве завдання — замовник хоче бути впевненим, що під час одночасного відкриття програми всі користувачі бачать коректні дані. Фізично.

Дуже дивний запит від замовника, що саме може піти не так?

тут ви мене підловили — дійсно, правильно було написати одночасно (concurrent), як це і називається в документації asyncio docs.python.org/...​unning-tasks-concurrently

І гарна сттаття, дякую!

Дуже цікаво, дякую, на днях треба спробувати.
А як щодо асинхронного виконання в pytest?

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

Встановив плагін pytest-xdist, все працює паралельно. Без змін в коді. Вже готую дописп про сетап пайтесту

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