docs: add Playwright Codegen section to README
Описан workflow визуальной записи тестов: - Команды запуска codegen (с сохранением в файл и без) - Порядок работы: запуск → авторизация → запись → адаптация - Полный пример: сырой вывод Codegen → класс с шагами - Таблица преобразований: что убирается и что добавляется
This commit is contained in:
130
README.md
130
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 в отчёте |
|
||||
|
||||
Reference in New Issue
Block a user