see-smc-autotest/GUIDE.md

17 KiB
Raw Blame History

Как создать автотесты для другого проекта

Этот гайд описывает полный цикл создания автотестов для SEE и SMC на любом проекте — от первого запуска до полного набора asserts.

Архитектура тестов

Тесты универсальные: не содержат хардкода имён моделей. Всё привязывается динамически:

Компонент Где Что делает
TEXT_RULES В начале каждого теста По ключевым словам в имени модели подбирает текст для запроса
DEFAULT_HOST / DEFAULT_PORT В начале каждого теста Куда стучаться (меняешь под свой проект)
asserts.json Отдельный файл Опциональные проверки — какой ответ ожидается от каждой модели

Шаг 1: Подготовка тестов к новому проекту

Скопируй test_see_models.py и/или test_smc_models.py в репозиторий нового проекта.

1.1 Укажи адрес сервера

В начале каждого тестового файла поменяй DEFAULT_HOST и DEFAULT_PORT:

DEFAULT_HOST = "10.101.60.27"   # IP вашего SEE/SMC
DEFAULT_PORT = 6184             # порт SEE: 6184, SMC: 6181

1.2 Настрой TEXT_RULES для своих моделей

TEXT_RULES — список (keyword, text). Первое совпадение побеждает, поэтому специфичные правила должны идти раньше общих.

Принцип: для каждой модели нужен текст, который гарантированно вернёт непустой ответ.

Пример для SEE (test_see_models.py):

TEXT_RULES = [
    # специфичные — раньше
    ("fio", "Иванов Иван Иванович"),       # модель ФИО → имя
    ("date", "на завтра"),                 # модель даты → фраза с датой
    ("phone", "8 913 456 78 90"),          # модель телефона → номер
    ("number", "пятьсот двадцать три"),     # модель числа → число прописью
    ("weekday", "в пятницу"),              # модель дня недели → день
    ("mobilizac", "оператор"),             # конкретная модель
    ("trud", "зарегистрироваться в цзн"),   # конкретная модель
    # общие — позже
    ("mfc", "записаться в мфц"),            # fallback для всего MFC
    ("test", "test message"),               # fallback для тестовых
]

Как подобрать правила для нового проекта:

  1. Посмотри список моделей: curl http://HOST:PORT/SEE_OR_SMC/models
  2. Для каждой модели подбери текст, который точно вернёт ответ
  3. Сгруппируй по ключевым словам (одно правило может покрыть несколько моделей)
  4. Расположи специфичные правила выше, общие — ниже

Пример для SMC (test_smc_models.py):

TEXT_RULES = [
    ("филиал", "родники"),                     # филиалы → название филиала
    ("offices", "родники"),
    ("мфц", "записаться в мфц"),               # модели МФЦ
    ("mfc", "записаться в мфц"),
    ("ekc", "записаться в екц"),               # модели ЕКЦ
    ("екц", "записаться в екц"),
    ("minsoc", "какие выплаты"),               # минсоц
    ("техническая", "подключите оператора"),    # техподдержка
    ("тест", "тестовый запрос"),
]

TEXT_RULES покрывает только типовые модели (fio, date, phone, mfc, zags...) — те, для которых по ключевому слову можно угадать подходящий текст. Одно правило покрывает десятки похожих моделей.

Для узкоспецифичных моделей проекта, где ключевое слово не даёт нужной точности, используй text в asserts (см. Шаг 3.6).

Шаг 2: Первый запуск без asserts

Запусти тест с -v (verbose), чтобы увидеть каждую модель и её ответ:

python3 test_see_models.py --host 10.101.60.25 --port 6184 -v

Вывод будет примерно таким:

── PRETRAINED ──────────────────────────────────────────────
  ✓ date  → 2026-06-24
  ✓ number  → 523
  ✓ fio  → Ф:"Иванов" И:"Иван" О:"Иванович"
  ─── 6 passed, 0 empty

── CUSTOM ──────────────────────────────────────────────
  ✓ zags  → отдел_центрального_оовосибирска
  ✓ weekday  → пятница
  ✗ fio2  → empty
  ✗ Начало диалога  → empty
  ─── 200 passed, 9 empty

Из вывода ты видишь:

  • Какие модели работают (✓ модель → результат)
  • Какие всегда пустые (✗ модель → empty)
  • Какие есть хеш-варианты и бэкапы (у них тот же префикс, но с ~hash или -backup)

Шаг 3: Создание asserts

3.1 Правило min_found

Тип модели min_found Почему
Базовая (без суффикса) 1 Должна всегда отвечать
Хеш-вариант (~4f2d37c9...) 0 Копия базы для тестирования, может не работать
-backup 0 Бэкап, может не работать
-planned 0 Запланированная, ещё не готова
-new 0 Экспериментальная, может не работать

3.2 Формат для SEE (entity-модели)

SEE возвращает сущности с полями text, calculated, confidence:

{
  "asserts": [
    {
      "model": "fio",
      "text": "Иванов Иван Иванович",
      "checks": {
        "min_found": 1,
        "text_contains": "иван",
        "calculated_contains": "Ф:",
        "confidence_min": 0.3
      }
    }
  ]
}
Поле checks Что проверяет Пример
min_found Минимум сущностей в ответе 1
text_contains Подстрока в text первой сущности "иван"
calculated_contains Подстрока в calculated первой сущности "Ф:"
confidence_min Минимальный confidence первой сущности 0.3

Где брать значения: из вывода -v. Например:

✓ fio  → Ф:"Иванов" И:"Иван" О:"Иванович"
                 ↑ берём отсюда подстроки для text_contains и calculated_contains

3.3 Формат для SMC (classifier-модели)

SMC возвращает классы с полями class и confidence:

{
  "asserts": [
    {
      "model": "МФЦ НСК",
      "text": "записаться в мфц",
      "checks": {
        "min_found": 1,
        "text_contains": "Запись",
        "confidence_min": 0.5
      }
    }
  ]
}
Поле checks Что проверяет Пример
min_found Минимум классов в ответе 1
text_contains Подстрока в class первого класса "Запись"
confidence_min Минимальный confidence первого класса 0.5

Где брать значения: из вывода -v:

✓ МФЦ НСК  → Предварительная запись (1.000)
              └── text_contains: "Запись"
                        └── confidence_min: 0.5

3.4 Полный assert для каждой строки -v

Проходишь вывод -v и для каждой строки создаёшь запись:

Вывод -v Запись в asserts
✓ fio → Ф:"Иванов" И:"Иван" О:"Иванович" {"model": "fio", "text": "Иванов Иван Иванович", "checks": {"min_found": 1, "calculated_contains": "Ф:", "confidence_min": 0.3}}
✓ weekday → пятница {"model": "weekday", "checks": {"min_found": 1, "text_contains": "пятница"}}
✓ zags~ffb403 → ... (хеш) {"model": "zags~ffb403", "checks": {"min_found": 0}}
✗ fio2 → empty {"model": "fio2", "checks": {"min_found": 0}}

3.5 Поле text в assert

Поле text в assert — опционально. Если оно есть, оно переопределяет pick_text().

Когда указывать text:

  • Модель работает с конкретным текстом, отличным от того что подбирает pick_text
  • Например: модель service_mfc возвращает услуги, но pick_text даёт "записаться в мфц" — лучше явно указать "хочу получить водительское удостоверение"

Когда НЕ указывать text:

  • pick_text() уже подбирает правильный текст
  • Для хеш-вариантов и бэкапов — используй тот же текст что у базовой модели (укажи явно, чтобы не зависеть от порядка pick_text)

Важно: если указываешь text для хеш-варианта или бэкапа, используй тот же текст, что для базовой модели. Разные тексты могут не работать для копий.

Пример:

// Базовая модель
{"model": "zags", "text": "загс центрального района", "checks": {"min_found": 1}}

// Хеш-вариант — тот же текст!
{"model": "zags~ffb403fff9f5802d53aac8a5c844af26", "text": "загс центрального района", "checks": {"min_found": 0}}

3.6 Когда TEXT_RULES не хватает

Философия тестов — два уровня проверки:

Уровень Инструмент Вопрос
1 — санитарный TEXT_RULES Модель живая? Отвечает хоть что-то?
2 — проверочный asserts Модель отвечает правильно?

TEXT_RULES даёт быстрый ответ «живая/мёртвая» для типовых моделей. Но есть модели, которым нужен специфичный текст, недоступный для угадывания по ключевому слову.

Пример: модель Конкретика по УК~ffb403... — TEXT_RULES по ключевому слову "конкретик" возвращает "конкретный вопрос". Текст слишком размытый, модель не находит сущностей и возвращает пустой ответ.

Решение: добавить text в assert с точной формулировкой:

{
  "model": "Конкретика по УК~ffb403fff9f5802d53aac8a5c844af26",
  "text": "Найти свою УК",
  "checks": {"min_found": 0}
}

Это не баг, а дизайн:

  • TEXT_RULES универсален и переносим между проектами (скопировал тесты — работает)
  • asserts пишется под конкретный проект и покрывает специфичные модели
  • Без asserts — быстрый санитарный прогон, с asserts — полная валидация

Шаг 4: Запуск с asserts

python3 test_see_models.py --host 10.101.60.25 --port 6184 --asserts see_asserts.json -v

Теперь для каждой модели:

  • — ответ непустой, проверки asserts пройдены
  • ✗ → empty — ответ пустой (но min_found: 0, тест проходит)
  • ✗ → assert fail — ответ есть, но не прошёл проверки (тест падает)

Шаг 5: Исправление проблем

Модель возвращает пустой ответ, а должна работать

  1. Проверь текст в assert — попробуй другой текст напрямую через curl:
    curl "http://HOST:PORT/see/entities/MODEL?text=ТЕКСТ&similarity=70"
    
  2. Если другой текст работает — обнови text в assert
  3. Если никакой текст не работает — модель действительно пустая, оставь min_found: 0

Модель проходит без asserts, но падает с asserts

Проверь значения в checks:

  • text_contains — проверь, что подстрока действительно есть в ответе
  • calculated_contains — только для SEE entity-моделей
  • confidence_min — возможно завышен, поставь 0.1 для ненадёжных моделей

Хеш-вариант работает без asserts, но с asserts — пустой

Это значит assert для хеш-варианта переопределяет text на неправильный. Убедись, что text совпадает с базовой моделью.

Полный пример: с нуля до готового набора

Допустим, у тебя новый проект с SEE на 10.10.10.10:6184.

# 1. Первый запуск — смотрим что есть
python3 test_see_models.py --host 10.10.10.10 --port 6184 -v

# 2. Вывод показывает 50 моделей. Создаём see_asserts.json:
#    - Для каждой базовой модели → min_found: 1 + проверки из ответа
#    - Для хеш-вариантов и бэкапов → min_found: 0
#    - Для пустых → min_found: 0

# 3. Запускаем с asserts
python3 test_see_models.py --host 10.10.10.10 --port 6184 --asserts see_asserts.json

# 4. Если есть ✗ assert fail — правим checks в asserts
# 5. Повторяем 3-4 пока все не пройдут

Структура репозитория после настройки

мой-проект/
├── test_see_models.py      # тест SEE (скопирован, изменён DEFAULT_HOST/PORT и TEXT_RULES)
├── test_smc_models.py      # тест SMC (опционально)
├── see_asserts.json        # проверки для SEE
├── smc_asserts.json        # проверки для SMC (опционально)
└── README.md               # краткое описание

Важные замечания

  1. Порядок правил в TEXT_RULES важен — специфичные ключевые слова ("fio", "phone") должны быть выше общих ("mfc", "test").

  2. Не указывай text в assert без необходимости — если pick_text() уже подбирает правильный текст, не переопределяй. Каждый лишний text в assert — потенциальный источник расхождений.

  3. Хеш-варианты и бэкапы — всегда min_found: 0. Они могут не работать, и это нормально.

  4. confidence_min для ненадёжных моделей — ставь 0.1, не 0.5. Даже минимальный confidence лучше чем пустой ответ.

  5. _find_assert ищет сначала точное совпадение — модель ekc_smc-backup не перепутается с ekc_smc. Порядок записей в asserts не критичен.

  6. Проверяй на всех серверах — если у тебя несколько инсталляций (dev/stage/prod), гоняй тесты на каждой:

for host in 10.101.60.25 10.101.60.26 10.101.60.27; do
    python3 test_see_models.py --host $host --port 6184 --asserts see_asserts.json
done