Целый раздел ТЗ, от которого не было ни одной функции. - Учётные записи: завести, сменить роль и службу, заблокировать, сбросить пароль. Обучающемуся заводится и карточка курсанта — на ней висят профиль и проверка «это твой разбор». - Состояние компонентов: база, модели речи, эмбеддинги, провайдер LLM, версия классификатора, число живых занятий. Отдельной строкой — секрет сессии: значение по умолчанию не ошибка запуска, но на стенде это дыра, и увидеть её должен администратор, а не проверяющий на защите. - Журнал действий с фильтром, только на чтение. - Резервные копии: кнопка и make backup для cron. pg_dump берётся локальный, а если его нет — из контейнера базы; если нет ни того ни другого, администратор видит, чего не хватает, а кнопка не молчит. Границы роли выражены отсутствием маршрутов, а не проверками внутри них: в разделе нет ни одной точки, трогающей оценки или пишущей в аудит. Два теста проверяют это перебором маршрутов роутера — так запрет нельзя ослабить, случайно добавив обработчик. Найдено по ходу: тесты с базой падали в компании и проходили поодиночке. Движок SQLAlchemy кэшировался на процесс, а каждый TestClient поднимает свой событийный цикл — пул привязан к первому. Появился db.base.reset() и фикстура, дающая движок на тест. 193 теста зелёных (12 новых).
47 lines
1.8 KiB
Python
47 lines
1.8 KiB
Python
"""Общая настройка тестов.
|
||
|
||
Голосовой контур выключен: он грузит модели около десяти секунд, а проверяется
|
||
отдельно в `test_voice_pipeline.py`. Вход включён как на стенде, но тесты
|
||
логинятся через `dev-token` — так же, как `make lesson` (tasks/lct-23-auth-roles.md).
|
||
"""
|
||
|
||
import os
|
||
|
||
os.environ.setdefault("DEV_AUTH_BYPASS", "true")
|
||
|
||
import pytest # noqa: E402
|
||
|
||
from app.config import get_settings # noqa: E402
|
||
|
||
|
||
@pytest.fixture(autouse=True, scope="session")
|
||
def _dev_auth():
|
||
"""Флаг обхода читается один раз при создании настроек."""
|
||
get_settings.cache_clear()
|
||
settings = get_settings()
|
||
assert settings.dev_auth_bypass, "тесты должны ходить через dev-token"
|
||
yield
|
||
|
||
|
||
@pytest.fixture(autouse=True)
|
||
def _fresh_engine():
|
||
"""Движок базы — на тест, а не на процесс.
|
||
|
||
Пул соединений привязан к событийному циклу, в котором создан, а каждый
|
||
`TestClient` поднимает свой. Общий движок даёт «Future attached to
|
||
a different loop» на втором обращении к базе — тест падает не там, где
|
||
ошибка, и только в компании других тестов.
|
||
"""
|
||
from app.db import base
|
||
|
||
base.reset()
|
||
yield
|
||
base.reset()
|
||
|
||
|
||
@pytest.fixture
|
||
def as_instructor(client):
|
||
"""Клиент, вошедший преподавателем. Cookie живёт в самом TestClient."""
|
||
response = client.post("/api/auth/dev-token")
|
||
assert response.status_code == 200, response.text
|
||
return client
|