test: старт с минимальным окружением и страж «без БД и фронта» (M-8)

- test_app: приложение с Settings только из MinIO, адреса NATS и DEBUG
  стартует, /healthcheck отвечает 200 с uptime, version, nats.
- test_layout: в requirements.txt нет asyncpg, SQLAlchemy, alembic,
  smbprotocol, argon2-cffi, raisa_fastapi_protected_api; нет каталогов web/,
  api/alembic/, api/src/{db,models,repositories}/.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-10-04 03:48:34 +04:00
parent 8685441fcd
commit 479a76f81b
2 changed files with 46 additions and 0 deletions

View File

@ -143,6 +143,20 @@ async def test_nats_disabled_starts_nothing_and_healthcheck_reports_off(
assert events == ["s3.close"]
async def test_minimal_environment_starts_and_healthcheck_answers(
patched_app: Any, monkeypatch: pytest.MonkeyPatch, minimal_settings: Callable[..., Any]
) -> None:
"""Старт с минимальным окружением: только MinIO, адрес NATS и DEBUG (без seed/jwt, БД и SMB)."""
monkeypatch.setattr(patched_app, "settings", minimal_settings())
assert patched_app.settings.NATS_ENABLED is True
async with running_app(patched_app) as client:
response = await client.get("/healthcheck")
assert response.status_code == 200 # noqa: PLR2004 - HTTP 200
assert set(response.json()) == {"uptime", "version", "nats"}
async def test_nats_enabled_subscribes_worker_and_reports_ok(
patched_app: Any, monkeypatch: pytest.MonkeyPatch, events: list[str]
) -> None:

View File

@ -0,0 +1,32 @@
"""Страж spec «Сервис не зависит от БД и фронта» (DECISION-4): ни зависимостей БД/SMB/шаблонной авторизации, ни
каталогов фронта, миграций, моделей и репозиториев."""
import re
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parents[3]
REQUIREMENTS = REPO_ROOT / "api" / "requirements.txt"
FORBIDDEN_PACKAGES = (
"asyncpg",
"sqlalchemy",
"alembic",
"smbprotocol",
"argon2-cffi",
"raisa_fastapi_protected_api",
)
FORBIDDEN_DIRS = ("web", "api/alembic", "api/src/db", "api/src/models", "api/src/repositories")
@pytest.mark.parametrize("package", FORBIDDEN_PACKAGES)
def test_requirements_have_no_database_or_template_auth_packages(package: str) -> None:
name = re.sub(r"[-_.]", "[-_.]", package) # имена пакетов сравниваются по PEP 503: -, _ и . равнозначны
pattern = re.compile(rf"^\s*{name}\s*(?:[=<>!~;\[]|$)", re.IGNORECASE)
lines = REQUIREMENTS.read_text(encoding="utf-8").splitlines()
assert not [line for line in lines if pattern.match(line)]
@pytest.mark.parametrize("directory", FORBIDDEN_DIRS)
def test_no_frontend_or_database_directories(directory: str) -> None:
assert not (REPO_ROOT / directory).exists()