← Python мануфактура

Після цього уроку ви зможете

Конспект і таймкоди

0:00

Віртуальне середовище й залежності

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, а не вимога переписувати урок.

Перевірено 2026-07-31

2:43

Документація й перевірка інсталяції

У документації Playwright потрібно завжди перевіряти обрану мову: приклади для Node.js, Python, Java та .NET відрізняються. Після встановлення залежностей варто прочитати вивід pip і перевірити список пакетів у Python Interpreter. Окрім playwright і pytest, там з’являться їхні транзитивні залежності.

4:18

Структура тестів і правила іменування

Тести зручно тримати в окремому 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_.

7:54

Синхронний Playwright API і фікстура `page`

У курсі використовується синхронний API Playwright, щоб кроки тесту виконувалися послідовно без додаткової складності async/await.

Фікстуру можна типізувати класом Page, а PyCharm імпортує потрібне ім’я через quick fix:

```python
from playwright.sync_api import Page, expect

def test_open_home_page(page: Page):
...
```

Важливо імпортувати Page і expect саме з playwright.sync_api, а не з асинхронного API.

Термін

pytest fixture `page`

Fixture із pytest-playwright, яка надає ізольовану Playwright Page для тесту та прибирає ручне створення browser context у базовому сценарії.

10:03

Перехід на сторінку та перша перевірка

Тест відкриває сайт через page.goto(...), після чого expect(page).to_have_title(...) перевіряє заголовок вкладки. expect виконує очікування протягом заданого тайм-ауту, тому така перевірка стійкіша за миттєве порівняння значень.

```python
def test_open_home_page(page: Page):
page.goto("https://testomat.io")
expect(page).to_have_title("очікуваний заголовок")
```

Автодоповнення 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.

Потрібно: pytest, pytest-playwright, Playwright browser binaries

13:12

Встановлення браузерів Playwright

Після першого запуску тест може впасти, якщо встановлено 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.

16:33

Читання помилки й виправлення тесту

Після встановлення браузерів тест може падати вже через поведінкову причину: неправильний URL або невірний очікуваний заголовок. У виводі pytest важливо знайти нижню частину stack trace, expected і actual, а також посилання на рядок тесту.

Логи можна дати AI-помічнику для первинного пояснення, але висновок потрібно перевірити у власному коді та браузері. У прикладі тест стає зеленим після виправлення очікуваного title на фактичний. Ctrl+R повторює останній запуск без повторного вибору конфігурації.

Практика

Перетворити падіння title на діагностичний тест

  1. Створити test file з test_ prefix.
  2. Навмисно вказати неправильний expected title й запустити test.
  3. Знайти expected, actual і рядок падіння.
  4. Замінити перевірку на стійкий regex і повторити запуск.

Результат: Перший запуск падає з пояснюваної причини, другий проходить.

20:04

Запуск у headed-режимі

За замовчуванням браузер запускається без графічного вікна. Щоб бачити проходження сценарію, до конфігурації pytest додається headed-режим:

```ini
[pytest]
addopts = --headed
```

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

Термін

headed mode

Режим запуску тесту з видимим browser window; у Playwright pytest вмикається прапорцем --headed.

21:44

Пошук кнопки Login і strict mode

Для перевірки видимості кнопки використовується expect(locator).to_be_visible(). У відео порівнюються перші варіанти локаторів:

- CSS-клас: .login-item;
- текстовий локатор: page.get_by_text("Login");
- точний текст: page.get_by_text("Login", exact=True).

Якщо локатор знаходить кілька вузлів, Playwright у strict mode не виконує дію навмання. Потрібно зробити критерій однозначним, а не бездумно брати перший елемент. exact=True обмежує пошук повним текстовим збігом; його документацію можна відкрити через швидку довідку PyCharm.

Уточнення

Не обходьте strict mode індексом без причини

Якщо locator знаходить кілька elements, зробіть критерій унікальним. .first і .nth() приховують неоднозначність та можуть почати діяти на інший element після зміни DOM.

Практика

Зробити Login locator однозначним

  1. Знайти всі збіги тексту Login у DevTools.
  2. Побудувати locator з role/name або стабільним attribute.
  3. Перевірити, що locator знаходить рівно один видимий element.

Результат: Дія не потребує .first або випадкового індексу.

27:59

Нестабільні локатори та Local History

Локатор, що випадково пройшов один раз, ще не є стабільним. Класи можуть повторюватися, а на сторінці можуть одночасно існувати видимий і прихований варіанти одного елемента. Перед використанням CSS-селектора його потрібно вставити в пошук DevTools і перевірити кількість та порядок знайдених вузлів.

PyCharm Local History дає змогу подивитися попередні версії файлу й відновити робочий варіант навіть без окремого Git-коміту. Це корисно для локальних експериментів, але не замінює контроль версій.

30:59

Комбінування CSS-умов

Коли одного класу недостатньо, селектор можна зробити однозначнішим, поєднавши клас з атрибутом посилання:

```css
a.login-item[href="/users/sign_in"]
```

Це означає: знайти один елемент <a>, який одночасно має клас login-item і заданий href. Наприкінці уроку пропонується самостійно потренувати пошук інших елементів, але не копіювати довгі згенеровані CSS/XPath-ланцюжки без перевірки їхньої стабільності.

Джерела та додаткові матеріали