Перейти к содержанию

Смоук-чеклист

Большую часть поведения проверяют автоматические тесты. Здесь собраны процедуры для наборов в настоящем QGIS и короткий список проверок, которым ещё нужен человек.

Автоматические наборы

  • python3 -m unittest discover -s tests -t . — быстрый набор. Идёт без QGIS.
  • tests/real_qgis_smoke.py ставит собранный ZIP в настоящий QGIS.
  • tests/real_qgis_workflows.py гоняет живые сценарии со слоями, Processing и жизненным циклом Qt, проверки экранов и tests/real_qgis_e2e.py.
  • tests/real_qgis_e2e.py ведёт весь плагин так, как это делает человек: печатает запрос, отправляет, применяет, останавливает и откатывает. Модель — tests/e2e_model.py, заскриптованный OpenAI-совместимый сервер на 127.0.0.1, который запоминает каждый запрос.

Чтобы добавить сквозной сценарий, унаследуйте ScenarioCase, поставьте ходы модели через say(), call(), calls() и fail(), затем ведите панель через ask(), apply() и wait_idle(). Сценарий падает на неожиданном запросе или неиспользованном ходе. Наборы запускаются Python из QGIS:

QT_QPA_PLATFORM=offscreen python3 tests/real_qgis_workflows.py

Эталоны экранов

tests/real_qgis_visual.py собирает каждый экран без модели и проверяет его тремя способами: структуру виджетов по JSON-эталонам в tests/data/ui/structure (только английский), обрезанный текст и выход за границы на английском и русском (UI_LOCALE=ru) и пиксели по PNG-эталонам в tests/data/ui/pixels. Пиксели сравниваются только в задаче CI ui-pixels, на одном образе QGIS, закреплённом по digest. Каждый запуск CI прикладывает галерею экранов index.html.

После намеренного изменения интерфейса перезапишите эталоны структуры и просмотрите diff JSON:

UI_UPDATE_GOLDENS=1 QT_QPA_PLATFORM=offscreen python3 tests/real_qgis_workflows.py real_qgis_visual

Пиксельные эталоны берутся только из закреплённого образа, никогда из настольного QGIS. Либо скопируйте картинки ui-actual из артефакта ui-pixels упавшего запуска в tests/data/ui/pixels, либо запустите тот же образ локально:

docker run --rm --platform linux/amd64 -v "$PWD":/repo -w /repo \
  -e QT_QPA_PLATFORM=offscreen -e UI_PIXEL_BASELINE=1 -e UI_UPDATE_GOLDENS=1 \
  qgis/qgis@sha256:23c12670e69909e8659a5c098aa307996735a5763b9ff9c3268bdeeee1a10916 \
  sh -c 'python3 tests/real_qgis_workflows.py real_qgis_visual && UI_LOCALE=ru python3 tests/real_qgis_workflows.py real_qgis_visual'

Сценарии с настоящей моделью

tests/real_qgis_live.py даёт настоящей модели обычные задачи: раскраску по классам, вопрос на подсчёт, подписи, буфер в метрах. Проверяется только результат, потому что путь модель выбирает сама. Падение значит, что промпт, навык или схема инструмента сбивает настоящие модели, или провайдер что-то поменял.

В CI его гоняет workflow live-model в QGIS. Он никогда не запускается на push и pull request: запускайте его из вкладки Actions или поставьте галочку live_model_check при выпуске. Нужны переменные LIVE_MODEL_URL и LIVE_MODEL и секрет LIVE_MODEL_KEY. Траты ограничены на запуск, на набор и таймаутом задачи; поставьте лимит трат и у провайдера.

Локально подойдёт любой OpenAI-совместимый сервер, с локальной моделью — бесплатно:

LIVE_MODEL_URL=http://localhost:11434/v1 LIVE_MODEL=qwen3 LIVE_MODEL_KEY=local \
  QT_QPA_PLATFORM=offscreen python3 tests/real_qgis_workflows.py real_qgis_live

Потолки токенов

Две проверки сверяют расход с tests/data/token_ceilings.json:

  • Скриптовая, на каждый push. tests/real_qgis_e2e.py измеряет самый большой системный промпт, самый большой список схем инструментов и самый маленький запрос (base_chars) в символах и сравнивает с разделом scripted. Числа сохраняются в request_sizes.json в артефакте e2e-screens-*.
  • С настоящей моделью, вручную и перед выпуском. tests/real_qgis_live.py записывает токены промпта, ответа, их сумму и число запросов каждого сценария в live_usage.json (артефакт live-token-usage) и сравнивает с разделом live. Потолки относятся к модели, на которой их измерили; с другой моделью запуск только сообщает числа. Workflow задаёт LIVE_REQUIRE_CEILINGS=1, поэтому там сценарий без потолка падает.

Обновляйте потолки, только когда расход изменился намеренно, и пишите причину в коммите. Потолки для настоящей модели стройте по двум-трём запускам workflow live-model: скрипт берёт наибольшее значение каждой метрики и добавляет запас (30 % для настоящей модели, 10 % для скриптовой).

gh run download <run-id> -n live-token-usage -D /tmp/live-1
python3 tests/token_ceilings.py /tmp/live-1/live_usage.json /tmp/live-2/live_usage.json

Скриптовые потолки берутся из одного прогона скриптовых сценариев:

E2E_ARTIFACTS=/tmp/e2e QT_QPA_PLATFORM=offscreen python3 tests/real_qgis_workflows.py real_qgis_e2e
python3 tests/token_ceilings.py /tmp/e2e/request_sizes.json

Перед коммитом просмотрите diff: резко выросший потолок — это и есть регрессия, ради которой проверка существует.

Ручные проверки

Им нужен настоящий провайдер, настоящий сетевой сервис или взгляд человека.

  1. Провайдеры. Проверка подключения и один запуск с вызовами инструментов на OpenAI, Anthropic (формат auto шлёт на /messages), OpenRouter, Google Gemini и Ollama по адресу http://localhost:11434/v1 с пустым ключом. Удалённый адрес без ключа сообщает, что нет ключа.
  2. Рассуждение. Локальная рассуждающая модель (дистиллят DeepSeek-R1, QwQ) держит рассуждение в свёрнутой строке Размышление, а не в ответе. Anthropic с бюджетом размышлений 4096 доводит запуск с инструментами до конца. DeepSeek с включённым рассуждением отвечает на два вопроса с инструментами в одном разговоре без ошибки 400 о reasoning_content.
  3. Русский QGIS. Переключите интерфейс QGIS на русский и перезапустите. Панель, настройки и карточка плана на русском, с верными формами числа (1 шаг, 2 шага, 5 шагов). Немецкий откатывается на английский. Агент отвечает на том языке, на котором вы пишете.
  4. Темы. В светлом и тёмном QGIS, а также со Светлой темой панели в тёмном QGIS читаются панель, настройки, списки @ и /, меню и карточки. Значки чёткие на экране с высокой плотностью.
  5. Движение. Компас качается, пока агент работает, и успокаивается, когда он закончил. Списки действий и Размышление сворачиваются плавно, даже при многих щелчках подряд.
  6. OpenStreetMap. Скачай кафе в Твери добавляет точечный слой. Охват шире пяти градусов отклоняется до отправки.
  7. Открытые данные. Поиск Sentinel-2 просит согласия с названием Planetary Computer и перечисляет снимки; загрузка одного добавляет растр. Добавь регионы Кении добавляет 47 регионов. Коннектор, выключенный в настройках, отклоняется.
  8. Веб-инструменты. Поиск, чтение страницы и геокодирование каждый раз спрашивают. Адрес https://nominatim.openstreetmap.org как свой геокодер не сохраняется.
  9. Другие плагины. С установленным qgis2web запуск его экспорта спрашивает подтверждение для опасного действия и открывает его окно. Установка плагина из репозитория спрашивает дважды, после чего плагин виден в Управлении модулями, а его алгоритмы — в панели Processing.
  10. Долгий шаг. Буфер на слое в десятки тысяч объектов: карта двигается, пока он идёт, шаг показывает прогресс, ■ отменяет его и шаги после него.
  11. Перезапуск. После перезапуска QGIS разговор возвращается со списками действий и карточками плана, а уточняющий вопрос опирается на прежний контекст. Заметки проекта остаются при своём проекте.
  12. Выгрузка. Перезагрузка плагина во время запроса не роняет QGIS.
  13. Журнал прогона. Включите Журнал прогона в Настройки → Приватность и примените план. Чат показывает путь в ai_agent_runs; у папки режим 0700, у файла 0600.
  14. Макет печати. Собери лист А4 с картой, заголовком, легендой и масштабной линейкой и экспортируй в PDF: PDF открывается, а на модели со зрением проверка после применения смотрит на отрисованный макет.
  15. История. Хранить разговоры 7 дней удаляет более старые разговоры, но не открытый. Удалить историю и журналы сначала спрашивает, затем очищает и то и другое.