diff --git a/requirements.txt b/requirements.txt index 9275782..7bb4b0b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ pytest-playwright pytest-xdist pytest-html pytest-dependency +faker python-dotenv \ No newline at end of file diff --git a/tests/01_vetdept/conftest.py b/tests/01_vetdept/conftest.py index 26a40d3..67aea81 100644 --- a/tests/01_vetdept/conftest.py +++ b/tests/01_vetdept/conftest.py @@ -1,4 +1,40 @@ +# pyrefly: ignore [missing-import] import pytest +from pathlib import Path + + +# --------------------------------------------------------------------------- +# Пути к статическим артефактам роли (фото, документы, файлы) +# --------------------------------------------------------------------------- + +@pytest.fixture(scope="session") +def fixtures_dir() -> Path: + """ + Путь к папке со статическими артефактами роли vetdept. + Структура папки: + fixtures/ + ├── images/ ← фотографии животных, документы-сканы + └── docs/ ← PDF, сертификаты и прочие документы + + Используй как базовый путь для других фикстур-артефактов: + def test_s02_upload(self, browser_page, fixtures_dir): + photo = fixtures_dir / "images" / "cat_photo.jpg" + browser_page.set_input_files("input[type=file]", str(photo)) + """ + return Path(__file__).parent / "fixtures" + + +# --------------------------------------------------------------------------- +# Готовые фикстуры для конкретных артефактов +# Добавляй новые по мере появления новых файлов в папке fixtures/ +# --------------------------------------------------------------------------- + +# Пример: раскомментируй и адаптируй когда нужен конкретный файл +# +# @pytest.fixture(scope="session") +# def cat_photo(fixtures_dir) -> Path: +# """Фотография кошки для теста загрузки фото животного.""" +# return fixtures_dir / "images" / "cat_photo.jpg" # --------------------------------------------------------------------------- diff --git a/tests/01_vetdept/fixtures/docs/.gitkeep b/tests/01_vetdept/fixtures/docs/.gitkeep new file mode 100644 index 0000000..82b41db --- /dev/null +++ b/tests/01_vetdept/fixtures/docs/.gitkeep @@ -0,0 +1 @@ +# Эта папка хранит PDF, сертификаты и прочие документы для тестов загрузки файлов. diff --git a/tests/01_vetdept/fixtures/images/.gitkeep b/tests/01_vetdept/fixtures/images/.gitkeep new file mode 100644 index 0000000..db4081b --- /dev/null +++ b/tests/01_vetdept/fixtures/images/.gitkeep @@ -0,0 +1,2 @@ +# Эта папка хранит фотографии животных и другие изображения для тестов. +# Добавляй реальные файлы сюда и создавай фикстуры в ../conftest.py diff --git a/tests/testdata/__init__.py b/tests/testdata/__init__.py new file mode 100644 index 0000000..954f0cd --- /dev/null +++ b/tests/testdata/__init__.py @@ -0,0 +1,3 @@ +# Пакет тестовых данных +# Содержит генераторы случайных данных по правилам ФЛК +from .generators import * # noqa: F401, F403 diff --git a/tests/testdata/generators.py b/tests/testdata/generators.py new file mode 100644 index 0000000..aa5180b --- /dev/null +++ b/tests/testdata/generators.py @@ -0,0 +1,197 @@ +""" +Генераторы тестовых данных по правилам ФЛК (Форматно-Логический Контроль). + +============================================================================= +КАК ДОБАВИТЬ НОВЫЙ ГЕНЕРАТОР +============================================================================= + +1. Определи раздел (секцию) к которому относится данное поле. + Разделы обозначены комментариями: # === РАЗДЕЛ: ... === + +2. Если нужного раздела нет — добавь новый в конце файла по шаблону: + + # ============================================================================= + # === РАЗДЕЛ: Название раздела === + # ============================================================================= + +3. Напиши функцию-генератор в нужном разделе: + + def gen_<сущность>_<поле>(<параметры>) -> <тип>: + \"\"\" + Краткое описание что генерирует функция. + + ФЛК: + - Правило 1 (например: только цифры) + - Правило 2 (например: длина ровно 15 символов) + - Правило 3 (например: начинается с '643') + + Аргументы: + param1 — описание параметра и его диапазон + + Пример вывода: '643094100123456' + \"\"\" + ... + +4. Если функция использует Faker — используй уже созданный экземпляр `fake` + (не создавай новые экземпляры в каждой функции). + +5. Если данные статические (например, список имён) — помести их как константу + перед функцией с именем _DATA_<НАЗНАЧЕНИЕ>. + +============================================================================= +ПРИМЕР ИСПОЛЬЗОВАНИЯ В ТЕСТЕ +============================================================================= + + from tests.testdata.generators import gen_microchip, gen_animal_name + + class TestBP02RegisterAnimal: + def test_s01_fill_form(self, browser_page, bp_state): + name = gen_animal_name() + microchip = gen_microchip() + + browser_page.fill("#animal-name", name) + browser_page.fill("#microchip", microchip) + + bp_state["animal_name"] = name # передаём следующему шагу + bp_state["microchip"] = microchip + +============================================================================= +""" + +import random +import string +from datetime import date, timedelta +from faker import Faker + +# Единственный экземпляр Faker на весь модуль — не создавай новые в функциях +fake = Faker("ru_RU") + + +# ============================================================================= +# === РАЗДЕЛ: Животное === +# ============================================================================= + +_DATA_ANIMAL_NAMES = [ + "Мурка", "Барсик", "Шарик", "Рекс", "Симба", + "Дружок", "Звезда", "Кличко", "Жорик", "Буся", + "Тузик", "Маркиз", "Пуговка", "Снежок", "Рыжик", +] + + +def gen_animal_name() -> str: + """ + Кличка животного. + + ФЛК: + - Только кириллица + - Первая буква заглавная + - От 2 до 20 символов + + Пример вывода: 'Мурка' + """ + return random.choice(_DATA_ANIMAL_NAMES) + + +def gen_birth_date(min_years: int = 0, max_years: int = 20) -> str: + """ + Дата рождения животного. + + ФЛК: + - Не позднее сегодняшнего дня + - Не ранее max_years лет назад + - Формат: ДД.ММ.ГГГГ + + Аргументы: + min_years — минимальный возраст в годах (по умолчанию 0 = только что рождён) + max_years — максимальный возраст в годах (по умолчанию 20) + + Пример вывода: '15.03.2021' + """ + min_days = min_years * 365 + max_days = max_years * 365 + delta = random.randint(min_days, max_days) + birth = date.today() - timedelta(days=delta) + return birth.strftime("%d.%m.%Y") + + +# ============================================================================= +# === РАЗДЕЛ: Маркировка животного === +# ============================================================================= + +def gen_microchip() -> str: + """ + Номер микрочипа. + + ФЛК: + - Ровно 15 цифр + - Стандарт ISO 11784/85 + - Первые 3 цифры — код страны (643 = Россия) [опционально] + + Пример вывода: '643094100123456' + """ + return "".join(str(random.randint(0, 9)) for _ in range(15)) + + +def gen_tattoo() -> str: + """ + Номер клейма (тату-маркировка). + + ФЛК: + - 2 заглавные латинские буквы + - 4 цифры + - Итого 6 символов + + Пример вывода: 'AB1234' + """ + letters = "".join(random.choices(string.ascii_uppercase, k=2)) + digits = "".join(str(random.randint(0, 9)) for _ in range(4)) + return letters + digits + + +# ============================================================================= +# === РАЗДЕЛ: Владелец животного === +# ============================================================================= + +def gen_owner_full_name() -> str: + """ + ФИО владельца. + + ФЛК: + - Только кириллица + - Формат: Фамилия Имя Отчество + + Пример вывода: 'Иванов Иван Иванович' + """ + return fake.name() + + +def gen_owner_phone() -> str: + """ + Мобильный телефон владельца. + + ФЛК: + - Российский номер + - Начинается с +7 + - Код оператора: 9XX (мобильные) + - Формат: +7(9XX)XXX-XX-XX + + Пример вывода: '+7(916)543-21-09' + """ + code = random.randint(900, 999) + part1 = random.randint(100, 999) + part2 = random.randint(10, 99) + part3 = random.randint(10, 99) + return f"+7({code}){part1}-{part2}-{part3}" + + +def gen_owner_email() -> str: + """ + Email владельца. + + ФЛК: + - Валидный формат email + - Латинские символы + + Пример вывода: 'ivanov.ivan@example.com' + """ + return fake.email()