From d156fa0664711c6c73cee2fc50c176c958f198ae Mon Sep 17 00:00:00 2001 From: VolandSZ <{E-MAIL}> Date: Tue, 1 Sep 2026 23:58:41 +0300 Subject: [PATCH] docs: add Playwright Codegen section to README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Описан workflow визуальной записи тестов: - Команды запуска codegen (с сохранением в файл и без) - Порядок работы: запуск → авторизация → запись → адаптация - Полный пример: сырой вывод Codegen → класс с шагами - Таблица преобразований: что убирается и что добавляется --- README.md | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/README.md b/README.md index 573c84e..255aa4b 100644 --- a/README.md +++ b/README.md @@ -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 в отчёте |