8.5 KiB
Проверка импорта на изолированном 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 для интеграционных тестов не используются.
Что проверяется
- Dry-run: все строки всех таблиц и состояния sequences совпадают до/после.
- Apply: одна вставка, одно обновление, пропуск отсутствующего сотрудника.
- Повторный импорт: ноль INSERT/UPDATE, неизменные таблицы/sequences.
- CHECK constraint тестовой БД вызывает ошибку третьего действия после UPDATE и успешного INSERT; все строки возвращаются в исходное состояние. Sequence может продвинуться при rollback — это ожидаемое поведение PostgreSQL.
- Обновление только года без raw_data сохраняет существующий JSONB.
- Поздние строки CSV дополняют метаданные; первое непустое значение сохраняется при конфликте, отчёт содержит названия конфликтующих полей. Повтор идемпотентен.
- Два последовательных crawl сохраняют CSV-статью, отсутствующую у ВШЭ; появившаяся статья получает HSE ID без второй записи и потери метаданных.
- Полный
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 используйте
отдельную инструкцию и compose.vps.yml: этот локальный
Compose не предназначен для запуска на сервере с работающими сервисами.
Первый шаг:
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.
Дальнейшие точные команды сохранены здесь для воспроизводимого запуска:
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-тестам или статическому чтению файлов.
После сохранения вывода тестов удалите именно этот тестовый проект:
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 и доступ к рабочей БД не изменялись.