Створення першого UI-тесту на Python із `pytest` та Playwright: робота у віртуальному середовищі, встановлення залежностей і браузерів, написання перевірки для Testomat.io, аналіз падіння та перші способи пошуку елементів.
Після цього уроку ви зможете
Пояснити роль .venv, pip, pytest-playwright і fixture page.
Створити тест, який pytest знаходить за naming conventions.
Встановити сумісні browser binaries Playwright і запустити тест у headless або headed mode.
Прочитати expected/actual у падінні та зробити locator однозначним у strict mode.
PyCharm зазвичай створює для нового Python-проєкту окреме віртуальне середовище .venv. Воно ізолює версію Python і бібліотеки конкретного проєкту від інших проєктів на комп’ютері.
У вбудованому терміналі активне середовище позначається префіксом на кшталт (.venv). Термінал можна відкрити через меню дій або гарячою клавішею (Option+F12 на macOS чи Alt+F12 у відповідній розкладці на Windows).
Для інтеграції Playwright із pytest встановлюється пакет:
```bash pip install pytest-playwright ```
Плагін надає готові pytest-фікстури, зокрема page, і бере на себе створення браузера, контексту та сторінки для тесту.
Що змінилося після запису
Playwright офіційно документує `uv` поруч із `pip`
АктуальноПоточний installation guide показує uv add pytest-playwright як підтриманий варіант поряд із pip і Poetry; це додатковий workflow, а не вимога переписувати урок.
У документації Playwright потрібно завжди перевіряти обрану мову: приклади для Node.js, Python, Java та .NET відрізняються. Після встановлення залежностей варто прочитати вивід pip і перевірити список пакетів у Python Interpreter. Окрім playwright і pytest, там з’являться їхні транзитивні залежності.
Тести зручно тримати в окремому Python package, а не у випадковій директорії. Package містить __init__.py, що явно позначає Python-структуру.
Для автоматичного виявлення pytest файл і тестова функція мають відповідати домовленостям іменування, наприклад:
```python def test_open_home_page(): ... ```
Назви Python-файлів, функцій і змінних записуються у snake_case. Підкреслення PyCharm та індикатор проблем у правому верхньому куті не варто ігнорувати: вони часто показують синтаксичну або типізаційну помилку ще до запуску.
Що змінилося після запису
`__init__.py` не є умовою pytest discovery
АктуальноPytest знаходить test modules і functions за naming conventions навіть без Python package. __init__.py впливає на import semantics і module names, але не є обов’язковим для базового discovery.
Перевірено 2026-07-31
Термін
test discovery
Правила, за якими pytest знаходить test modules і test functions; рекомендований базовий шаблон — test_*.py і функції з префіксом test_.
Тест відкриває сайт через page.goto(...), після чого expect(page).to_have_title(...) перевіряє заголовок вкладки. expect виконує очікування протягом заданого тайм-ауту, тому така перевірка стійкіша за миттєве порівняння значень.
Автодоповнення PyCharm шукає методи не лише за початком, а й за частиною назви. Методи з подвійними підкресленнями є службовими й у звичайному тесті не потрібні.
Приклад коду
Мінімальний Playwright pytest test
import re
from playwright.sync_api import Page, expect
def test_home_page_has_title(page: Page):
page.goto("https://playwright.dev/")
expect(page).to_have_title(re.compile("Playwright"))
Показує sync API, injected page fixture, navigation і web-first assertion без залежності від мінливого повного title.
Очікуваний результат: pytest знаходить один test і він проходить у Chromium.
Після першого запуску тест може впасти, якщо встановлено Python-пакет Playwright, але ще не завантажено сумісні браузери. Їх потрібно встановити окремо:
```bash playwright install ```
Якщо команда Playwright недоступна напряму, її можна запустити як Python-модуль:
```bash python -m playwright install ```
Playwright завантажує сумісні версії Chromium, Firefox і WebKit. Chromium є окремим браузерним рушієм; для перевірки саме встановленого Google Chrome його потрібно явно обрати в конфігурації.
Термін
browser binaries
Версії Chromium, Firefox і WebKit, сумісні з установленою версією Playwright та завантажувані окремою командою playwright install.
Після встановлення браузерів тест може падати вже через поведінкову причину: неправильний URL або невірний очікуваний заголовок. У виводі pytest важливо знайти нижню частину stack trace, expected і actual, а також посилання на рядок тесту.
Логи можна дати AI-помічнику для первинного пояснення, але висновок потрібно перевірити у власному коді та браузері. У прикладі тест стає зеленим після виправлення очікуваного title на фактичний. Ctrl+R повторює останній запуск без повторного вибору конфігурації.
Практика
Перетворити падіння title на діагностичний тест
Створити test file з test_ prefix.
Навмисно вказати неправильний expected title й запустити test.
Знайти expected, actual і рядок падіння.
Замінити перевірку на стійкий regex і повторити запуск.
Результат: Перший запуск падає з пояснюваної причини, другий проходить.
Якщо локатор знаходить кілька вузлів, Playwright у strict mode не виконує дію навмання. Потрібно зробити критерій однозначним, а не бездумно брати перший елемент. exact=True обмежує пошук повним текстовим збігом; його документацію можна відкрити через швидку довідку PyCharm.
Уточнення
Не обходьте strict mode індексом без причини
Якщо locator знаходить кілька elements, зробіть критерій унікальним. .first і .nth() приховують неоднозначність та можуть почати діяти на інший element після зміни DOM.
Практика
Зробити Login locator однозначним
Знайти всі збіги тексту Login у DevTools.
Побудувати locator з role/name або стабільним attribute.
Перевірити, що locator знаходить рівно один видимий element.
Результат: Дія не потребує .first або випадкового індексу.
Локатор, що випадково пройшов один раз, ще не є стабільним. Класи можуть повторюватися, а на сторінці можуть одночасно існувати видимий і прихований варіанти одного елемента. Перед використанням CSS-селектора його потрібно вставити в пошук DevTools і перевірити кількість та порядок знайдених вузлів.
PyCharm Local History дає змогу подивитися попередні версії файлу й відновити робочий варіант навіть без окремого Git-коміту. Це корисно для локальних експериментів, але не замінює контроль версій.
Коли одного класу недостатньо, селектор можна зробити однозначнішим, поєднавши клас з атрибутом посилання:
```css a.login-item[href="/users/sign_in"] ```
Це означає: знайти один елемент <a>, який одночасно має клас login-item і заданий href. Наприкінці уроку пропонується самостійно потренувати пошук інших елементів, але не копіювати довгі згенеровані CSS/XPath-ланцюжки без перевірки їхньої стабільності.