You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7.1 KiB
7.1 KiB
ШАГ 006 — Спринт 1: Инфраструктура + Создание тестов
Дата: 2026-03-21 Контекст: Мастер-класс по разработке системы тестирования сотрудников клиники.
Запрос
готов. поехали (начинаем Спринт 1)
Ответ
Реализован Спринт 1 в полном объёме: инфраструктура + создание тестов без авторизации. Спринт протестирован вручную в браузере, найдены и исправлены 4 бага.
Структура проекта после спринта
qa_test_app/
├── docker-compose.yml ← поднимает весь стек одной командой
├── .env.example
├── nginx/
│ └── nginx.conf ← / → frontend, /api/ → backend
├── backend/
│ ├── Dockerfile
│ ├── entrypoint.sh ← ждёт БД, запускает миграции, стартует сервер
│ ├── requirements.txt
│ ├── alembic.ini
│ ├── alembic/
│ │ ├── env.py ← async alembic, берёт URL из settings
│ │ ├── script.py.mako
│ │ └── versions/
│ │ └── 001_init.py ← создаёт таблицы tests, questions, answers
│ └── app/
│ ├── config.py ← настройки через pydantic-settings
│ ├── database.py ← async SQLAlchemy engine + session
│ ├── main.py ← FastAPI app, /api/health
│ ├── models/test.py ← ORM модели: Test, Question, Answer
│ ├── schemas/test.py ← Pydantic схемы с валидацией
│ └── api/tests.py ← REST эндпоинты
└── frontend/
├── Dockerfile
├── package.json
├── vite.config.ts
├── index.html
└── src/
├── App.tsx ← роутер + провайдеры
├── api/
│ ├── client.ts ← axios с baseURL=/api
│ └── tests.ts ← типы + функции запросов
└── pages/
├── TestList/ ← список тестов + кнопка создать
├── TestCreate/ ← форма создания теста
└── TestDetail/ ← просмотр теста с вопросами
API эндпоинты
| Метод | URL | Описание |
|---|---|---|
| GET | /api/health |
Проверка работы сервера |
| GET | /api/tests |
Список тестов |
| GET | /api/tests/{id} |
Детали теста с вопросами и ответами |
| POST | /api/tests |
Создать тест |
Схема БД
tests
id, title, description, passing_score, time_limit,
allow_navigation_back, is_active, version, created_at
questions
id, test_id → tests.id, text, order
answers
id, question_id → questions.id, text, is_correct
Валидация
Backend (Pydantic):
- Тест: минимум 7 вопросов, passing_score 0–100
- Вопрос: минимум 3 варианта ответа, хотя бы 1 правильный
Frontend (Ant Design Form):
- Те же правила воспроизведены на клиенте
- Nested Form.List для динамических вопросов и ответов
- Таймер показывается только при включённом переключателе (shouldUpdate)
Как запустить
docker compose up --build
Открыть браузер: http://localhost
- Список тестов → кнопка «Создать тест»
- Заполнить форму → нажать «Создать тест»
- Перейти к созданному тесту и увидеть все вопросы и ответы
http://localhost/api/health→{"status": "ok"}http://localhost/api/docs→ Swagger UI FastAPIhttp://localhost/api/redoc→ ReDoc документация
Баги, найденные и исправленные при ручном тестировании
| # | Симптом | Причина | Исправление |
|---|---|---|---|
| 1 | permission denied на entrypoint.sh |
docker-compose.yml монтирует ./backend:/app — volume перекрывает файлы образа, включая результат chmod +x из Dockerfile |
CMD ["bash", "entrypoint.sh"] вместо CMD ["./entrypoint.sh"] |
| 2 | No module named 'app' в Alembic |
Python не добавляет WORKDIR в sys.path автоматически |
ENV PYTHONPATH=/app в Dockerfile |
| 3 | nginx: host not found in upstream "backend" |
nginx резолвит upstream-хосты при старте, а backend ещё не поднялся | Docker DNS resolver 127.0.0.11 + set $backend — резолвинг откладывается до момента запроса |
| 4 | http://localhost/api/docs → 404 |
FastAPI по умолчанию отдаёт Swagger по /docs, а через nginx путь становится /api/docs → backend:8000/api/docs (не существует) |
Явно указать docs_url="/api/docs", redoc_url="/api/redoc", openapi_url="/api/openapi.json" в FastAPI |
Для джуниора: все четыре бага — типичные для первого запуска Docker + FastAPI + nginx. Запомни их, встретишь снова.
Ключевые решения для джуниора
Async SQLAlchemy 2.0:
async_sessionmaker+AsyncSession— не блокируем event loop при запросах к БДselectinloadдля жадной загрузки связей (вместо N+1 запросов)
Alembic async:
async_engine_from_config+connection.run_sync(do_run_migrations)- URL берётся из
app.config.settings— одно место для конфига
Docker Compose healthcheck:
dbобъявляетhealthcheck,backendждётcondition: service_healthy- Дополнительно
entrypoint.shвызываетpg_isreadyдля надёжности
TanStack Query:
useQueryдля чтения данных — кэш, loading state, error state из коробкиuseMutationдля создания —invalidateQueriesобновляет список после успеха
Следующие шаги
- Спринт 1: Инфраструктура + Создание тестов
- Спринт 2: Прохождение теста + результаты
- Спринт 3: Трекер результатов
- Спринт 4: Авторизация и роли
- Спринт 5: Уведомления в MAX