feat(seed): add API test-data seeding script and make testdata target
- scripts/seed.py: stdlib HTTP client, JPEG+EXIF via optional Pillow (PNG fallback), additive-only, dry-run - Makefile: testdata target with ALBUMS/PHOTOS/SEED/TIMEOUT and boolean flags - README: usage section; new dev-seed-data capability spec
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# dev-seed-data Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
Dev-инструмент, который наполняет запущенное приложение тестовыми данными через
|
||||
публичный API: альбомы, сгенерированные фотографии и сопутствующие сущности — без
|
||||
прямого доступа к базе данных и хранилищу.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Запуск и аутентификация
|
||||
Скрипт SHALL получать базовый URL, email и пароль из переменных окружения и SHALL
|
||||
аутентифицироваться через `POST /api/auth/login`, после чего SHALL выполнять все запросы
|
||||
с Bearer-токеном владельца. Пароль SHALL не приниматься аргументами командной строки и
|
||||
SHALL не выводиться в поток вывода.
|
||||
|
||||
#### Scenario: Успешный вход
|
||||
- **WHEN** заданы корректные переменные окружения и скрипт запущен
|
||||
- **THEN** скрипт получает access-токен и приступает к наполнению
|
||||
|
||||
#### Scenario: Неверные учётные данные
|
||||
- **WHEN** вход возвращает 401
|
||||
- **THEN** скрипт завершается с понятным сообщением и ненулевым кодом, не создавая данных
|
||||
|
||||
#### Scenario: Пароль не логируется
|
||||
- **WHEN** скрипт выводит ход выполнения
|
||||
- **THEN** пароль и токены в вывод не попадают
|
||||
|
||||
### Requirement: Создание альбомов и фотографий
|
||||
Скрипт SHALL создавать заданное параметрами число альбомов и фотографий в каждом от имени
|
||||
аутентифицированного владельца через `POST /api/albums` и
|
||||
`POST /api/albums/:id/photos`. Названия альбомов SHALL содержать метку прогона.
|
||||
|
||||
#### Scenario: Наполнение альбомами и фото
|
||||
- **WHEN** скрипт запущен с числом альбомов и фотографий на альбом
|
||||
- **THEN** создаются указанные альбомы и фотографии, а имена альбомов помечены меткой прогона
|
||||
|
||||
#### Scenario: Воспроизводимость
|
||||
- **WHEN** задан числовой seed
|
||||
- **THEN** структура и параметры генерируемых данных детерминированы для этого seed
|
||||
|
||||
### Requirement: Генерация изображений с EXIF
|
||||
Скрипт SHALL генерировать загружаемые изображения на лету. При доступной библиотеке Pillow
|
||||
он SHALL использовать JPEG с EXIF-метаданными (время съёмки, при необходимости GPS); при
|
||||
отсутствии Pillow он SHALL использовать PNG без EXIF, созданный на стандартной библиотеке.
|
||||
|
||||
#### Scenario: Pillow доступна
|
||||
- **WHEN** библиотека Pillow импортируется
|
||||
- **THEN** загружаемые файлы — JPEG с датой съёмки в EXIF
|
||||
|
||||
#### Scenario: Pillow отсутствует
|
||||
- **WHEN** библиотека Pillow недоступна
|
||||
- **THEN** скрипт продолжает работу, загружая PNG без EXIF
|
||||
|
||||
### Requirement: Опциональные сопутствующие сущности
|
||||
Скрипт SHALL создавать теги, комментарии, лайки, share-ссылки и инвайты только при явном
|
||||
включении соответствующими флагами; без флагов эти сущности SHALL не создаваться.
|
||||
|
||||
#### Scenario: Флаги выключены
|
||||
- **WHEN** скрипт запущен без опциональных флагов
|
||||
- **THEN** создаются только альбомы и фотографии
|
||||
|
||||
#### Scenario: Сопутствующие данные включены
|
||||
- **WHEN** включены флаги тегов, комментариев, лайков, share-ссылок или инвайтов
|
||||
- **THEN** соответствующие сущности создаются для части фотографий или альбомов
|
||||
|
||||
### Requirement: Ожидание генерации вариантов
|
||||
При включённом ожидании скрипт SHALL дожидаться появления превью, опрашивая
|
||||
`GET /api/photos/:id` до появления `thumb_url`, с ограничением по таймауту.
|
||||
|
||||
#### Scenario: Варианты сгенерированы
|
||||
- **WHEN** ожидание вариантов включено и варианты появились
|
||||
- **THEN** скрипт продолжает после появления `thumb_url`
|
||||
|
||||
#### Scenario: Таймаут ожидания
|
||||
- **WHEN** варианты не появились за отведённое время
|
||||
- **THEN** скрипт сообщает о таймауте и продолжает, не зависая бесконечно
|
||||
|
||||
### Requirement: Только-добавление и сухой прогон
|
||||
Скрипт SHALL работать в режиме только-добавления: SHALL не удалять и не изменять
|
||||
существующие данные. Повторные запуски SHALL добавлять новые данные, различимые по метке
|
||||
прогона. При сухом прогоне скрипт SHALL сообщать план и SHALL не выполнять изменяющих
|
||||
запросов.
|
||||
|
||||
#### Scenario: Повторный запуск
|
||||
- **WHEN** скрипт запускается повторно
|
||||
- **THEN** существующие данные сохраняются, а новые добавляются с новой меткой прогона
|
||||
|
||||
#### Scenario: Сухой прогон
|
||||
- **WHEN** включён режим сухого прогона
|
||||
- **THEN** скрипт не отправляет запросов, изменяющих данные
|
||||
|
||||
### Requirement: Минимум зависимостей
|
||||
Основной функционал скрипта SHALL работать на стандартной библиотеке Python, включая
|
||||
HTTP-клиент; Pillow SHALL быть необязательной зависимостью.
|
||||
|
||||
#### Scenario: Запуск без внешних пакетов
|
||||
- **WHEN** в окружении нет сторонних пакетов
|
||||
- **THEN** скрипт выполняет базовое наполнение с изображениями PNG без EXIF
|
||||
|
||||
### Requirement: Запуск через Make-цель
|
||||
Проект SHALL предоставлять Make-цель `testdata`, которая запускает скрипт наполнения и
|
||||
передаёт ему числовые и булевы параметры. Цель SHALL не дублировать логику скрипта.
|
||||
|
||||
#### Scenario: Передача параметров
|
||||
- **WHEN** цель запущена с заданными параметрами (число альбомов и фото, seed, булевы флаги)
|
||||
- **THEN** соответствующие значения и флаги передаются в скрипт наполнения
|
||||
|
||||
#### Scenario: Значения по умолчанию
|
||||
- **WHEN** цель запущена без параметров
|
||||
- **THEN** используются документированные значения по умолчанию
|
||||
Reference in New Issue
Block a user