# Проверка импорта на изолированном PostgreSQL Запускается средствами проекта: pytest, SQLAlchemy, psycopg и отдельный Docker Compose. Не использует production Compose, `.env`, SSH или данные сотрудников. PostgreSQL 16 и runner работают в отдельной `internal`-сети без опубликованных портов. Данные PostgreSQL находятся в tmpfs, без постоянных volumes. Базы: `miem_import_test` и `miem_crawl_test`. Все сотрудники, статьи и credentials синтетические; тестовые пароли непригодны для реальных систем. Dockerfile копирует только нужный код и requirements. Его отдельный dockerignore исключает `.git`, `.env`, файлы ключей/credentials, CSV владельца, данные `app/data` и остальные файлы workspace. Runtime не получает переменные хоста. CLI subprocess дополнительно получает только явно заданные тестовые libpq параметры; `.pgpass`/service-файлы отключены. Не изменяйте адрес `postgres-test` или имена тестовых БД для подключения к существующему серверу. Синтетическая роль `import_test` создаётся только init-скриптом одноразового тестового кластера. Fixture выдаёт ей документированные column grants и USAGE sequence. Проверяется отсутствие CREATE схемы, INSERT сотрудников, DELETE публикаций и sequence UPDATE. Это не создание временного доступа к рабочей БД. Таблицы создаются моделью приложения и очищаются только в тестовых БД. HTTP заблокирован test fixture; входные профили полного обхода подставляются локально. Это проверяет настоящий SQL, транзакции, savepoint и сериализацию JSON, но не парсинг сайта ВШЭ. Fixtures SQLite и подмена psycopg для интеграционных тестов не используются. ## Что проверяется 1. Dry-run: все строки всех таблиц и состояния sequences совпадают до/после. 2. Apply: одна вставка, одно обновление, пропуск отсутствующего сотрудника. 3. Повторный импорт: ноль INSERT/UPDATE, неизменные таблицы/sequences. 4. CHECK constraint тестовой БД вызывает ошибку третьего действия после UPDATE и успешного INSERT; все строки возвращаются в исходное состояние. Sequence может продвинуться при rollback — это ожидаемое поведение PostgreSQL. 5. Обновление только года без raw_data сохраняет существующий JSONB. 6. Поздние строки CSV дополняют метаданные; первое непустое значение сохраняется при конфликте, отчёт содержит названия конфликтующих полей. Повтор идемпотентен. 7. Два последовательных crawl сохраняют CSV-статью, отсутствующую у ВШЭ; появившаяся статья получает HSE ID без второй записи и потери метаданных. 8. Полный `run_crawl` обрабатывает двух сотрудников. Два HSE ID на одну CSV-запись откатывают savepoint первого, сохраняя JSONB, авторов, ID, хеш и updated_at; публикация второго сохраняется. Проверяются обе очередности ID и уже установленная привязка; неоднозначность отражается в CrawlError. Всего 10 PostgreSQL-тестов (восьмой сценарий параметризован). В обычном `python -m pytest -q` они пропускаются. Opt-in `MIEM_POSTGRES_INTEGRATION=1` разрешён только с точным тестовым DATABASE_URL Compose-проекта. ## Команды владельцу Выполняйте на локальной машине с Docker Engine/Compose v2 из корня репозитория после независимого ревью. Команды явно выбирают локальный Unix socket и очищают наследуемое окружение. Для Docker Desktop/Windows используйте Linux/WSL с доступным локальным `/var/run/docker.sock`. Для отдельного стенда на VPS используйте [отдельную инструкцию](postgresql-import-vps.md) и `compose.vps.yml`: этот локальный Compose не предназначен для запуска на сервере с работающими сервисами. Первый шаг: ```sh env -i PATH="$PATH" docker --host unix:///var/run/docker.sock version ``` Ожидается exit code 0 и секции `Client` и `Server`. `command not found`, `permission denied` или только Client с ошибкой подключения означает, что до запуска этого варианта нужен локальный Docker. При его отсутствии сначала выполните только read-only диагностику из инструкции VPS. Дальнейшие точные команды сохранены здесь для воспроизводимого запуска: ```sh env -i PATH="$PATH" docker --host unix:///var/run/docker.sock compose --env-file /dev/null --project-name miem-publication-integration -f tests/postgres/compose.yml config --quiet env -i PATH="$PATH" docker --host unix:///var/run/docker.sock compose --env-file /dev/null --project-name miem-publication-integration -f tests/postgres/compose.yml build tests env -i PATH="$PATH" docker --host unix:///var/run/docker.sock compose --env-file /dev/null --project-name miem-publication-integration -f tests/postgres/compose.yml up --abort-on-container-exit --exit-code-from tests ``` Первые две команды проверяют Compose и собирают runner с уже используемыми зависимостями. Сборка/скачивание образов требуют registry/PyPI, но тестовая runtime-сеть не имеет внешнего доступа и запросов к ВШЭ нет. При успехе третьей команды ожидаются `10 passed` и exit code 0. Фактическую совместимость образа, column grants и PostgreSQL можно считать подтверждённой **только после такого выполнения**, не по unit-тестам или статическому чтению файлов. После сохранения вывода тестов удалите именно этот тестовый проект: ```sh env -i PATH="$PATH" docker --host unix:///var/run/docker.sock compose --env-file /dev/null --project-name miem-publication-integration -f tests/postgres/compose.yml down ``` Это уничтожит только синтетические данные в tmpfs тестового PostgreSQL. Не используйте `docker system prune`, production Compose или удаление рабочих volumes. Перед повторным прогоном выполните этот же `down`, чтобы следующий кластер начинался с чистого init.sql; не запускайте два прогона одновременно. ## Статус подготовки В среде подготовки Docker отсутствует; настоящие PostgreSQL-тесты не запускались. Локально доступны только unit-тесты, проверка Python и статические проверки. Production/VPS и доступ к рабочей БД не изменялись.