docs: add Playwright Codegen section to README

Описан workflow визуальной записи тестов:
- Команды запуска codegen (с сохранением в файл и без)
- Порядок работы: запуск → авторизация → запись → адаптация
- Полный пример: сырой вывод Codegen → класс с шагами
- Таблица преобразований: что убирается и что добавляется
This commit is contained in:
VolandSZ
2026-09-01 23:58:41 +03:00
parent 932d0594a9
commit d156fa0664

130
README.md
View File

@ -285,3 +285,133 @@ def test_s01_fill_form(self, browser_page, bp_state):
def test_s02_upload(self, browser_page, bp_state, cat_photo):
browser_page.set_input_files("input[type=file]", str(cat_photo))
```
---
## Создание теста через визуальный рекордер (Codegen)
Playwright Codegen — встроенный инструмент записи действий в браузере.
Ты кликаешь, вводишь текст и переходишь по страницам — Codegen генерирует
Python-код, который воспроизводит твои действия.
### Запуск рекордера
```powershell
# Открыть браузер с рекордером (без авторизации)
.\venv\Scripts\playwright.exe codegen https://vet.goznak.ru
# Открыть браузер с рекордером и сохранить результат в файл
.\venv\Scripts\playwright.exe codegen https://vet.goznak.ru --output tests\codegen_draft.py
```
Откроются два окна:
- **Браузер** — управляй им как обычно: кликай, заполняй формы, переходи по разделам
- **Playwright Inspector** — в реальном времени показывает сгенерированный код
### Порядок работы
1. **Запусти рекордер** командой выше
2. **Авторизуйся** под нужной ролью (введи логин/пароль из `.env`)
3. **Выполни нужный бизнес-процесс** — все действия записываются автоматически
4. **Скопируй сгенерированный код** из Playwright Inspector
5. **Адаптируй код** под архитектуру проекта (см. ниже)
---
### Как адаптировать код из Codegen в архитектуру проекта
Codegen генерирует **плоский скрипт**, проект использует **класс с шагами**.
Ниже показано как преобразовать одно в другое.
#### До (вывод Codegen):
```python
from playwright.sync_api import Playwright, sync_playwright, expect
def run(playwright: Playwright) -> None:
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto("https://vet.goznak.ru/auth")
page.get_by_role("textbox", name="Email").fill("gz_vetstation@vet.goznak.ru")
page.get_by_role("textbox", name="Введите пароль").fill("A6wrpzpD5T")
page.get_by_role("button", name="Войти в аккаунт").click()
page.get_by_role("link", name="Животные").click()
expect(page).to_have_url("https://vet.goznak.ru/animals")
page.get_by_role("button", name="Добавить животное").click()
page.get_by_label("Кличка").fill("Мурка")
page.get_by_role("button", name="Сохранить").click()
expect(page.get_by_text("Мурка")).to_be_visible()
context.close()
browser.close()
with sync_playwright() as playwright:
run(playwright)
```
#### После (архитектура проекта):
```python
import os
import pytest
from playwright.sync_api import Page, expect
BASE_URL = os.getenv("BASE_URL", "https://vet.goznak.ru")
@pytest.mark.vetstation
@pytest.mark.usefixtures("browser_page")
class TestBP02AddAnimal:
"""
BP02: Добавление нового животного
Проверяет что пользователь может:
- Перейти в раздел Животные
- Открыть форму добавления
- Заполнить кличку и сохранить
- Убедиться что животное появилось в списке
"""
# Авторизация и логин/пароль — убраны полностью:
# этим занимается фикстура browser_page (см. tests/conftest.py)
@pytest.mark.dependency(name="BP02::s01")
def test_s01_go_to_animals(self, browser_page: Page, bp_state: dict):
"""Шаг 1: Перейти в раздел Животные"""
browser_page.get_by_role("link", name="Животные").click()
expect(browser_page).to_have_url(BASE_URL + "/animals", timeout=10000)
@pytest.mark.dependency(name="BP02::s02", depends=["BP02::s01"])
def test_s02_open_add_form(self, browser_page: Page, bp_state: dict):
"""Шаг 2: Открыть форму добавления животного"""
browser_page.get_by_role("button", name="Добавить животное").click()
expect(browser_page.get_by_label("Кличка")).to_be_visible(timeout=10000)
@pytest.mark.dependency(name="BP02::s03", depends=["BP02::s02"])
def test_s03_fill_and_save(self, browser_page: Page, bp_state: dict):
"""Шаг 3: Заполнить кличку и сохранить"""
from tests.testdata.generators import gen_animal_name
name = gen_animal_name() # случайное имя по ФЛК
browser_page.get_by_label("Кличка").fill(name)
browser_page.get_by_role("button", name="Сохранить").click()
bp_state["animal_name"] = name # передаём шагу 4
@pytest.mark.dependency(name="BP02::s04", depends=["BP02::s03"])
def test_s04_verify_in_list(self, browser_page: Page, bp_state: dict):
"""Шаг 4: Проверить что животное появилось в списке"""
expect(
browser_page.get_by_text(bp_state["animal_name"])
).to_be_visible(timeout=10000)
```
### Что изменилось при адаптации
| Было в Codegen | Стало в проекте |
|---|---|
| `browser.launch()` + `context.new_page()` | Фикстура `browser_page` (авто) |
| Явный логин/пароль в коде | Берётся из `.env` через фикстуру |
| Один плоский `def run()` | Класс с методами-шагами |
| Нет зависимостей между шагами | `@pytest.mark.dependency(depends=[...])` |
| Хардкод данных (`"Мурка"`) | Генераторы ФЛК (`gen_animal_name()`) |
| Нет передачи данных между шагами | `bp_state["key"] = value` |
| Нет отображения в отчёте | Docstring шага → колонка Test в отчёте |