Playwright — запускаємо тести одночасно for fun
Привіт друзі! Нещодавно відкрив для себе новий інструмент для автоматизації тестування — 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, вона з’їдає
Власне, це все, чим я хотів поділитись . Було цікаво?
7 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів