docs: GUIDE.md — полный гайд по созданию автотестов с нуля
This commit is contained in:
parent
3f7bd3861b
commit
4867e4cebc
303
GUIDE.md
Normal file
303
GUIDE.md
Normal file
@ -0,0 +1,303 @@
|
||||
# Как создать автотесты для другого проекта
|
||||
|
||||
Этот гайд описывает полный цикл создания автотестов для 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`:
|
||||
|
||||
```python
|
||||
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`):
|
||||
|
||||
```python
|
||||
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`):
|
||||
|
||||
```python
|
||||
TEXT_RULES = [
|
||||
("филиал", "родники"), # филиалы → название филиала
|
||||
("offices", "родники"),
|
||||
("мфц", "записаться в мфц"), # модели МФЦ
|
||||
("mfc", "записаться в мфц"),
|
||||
("ekc", "записаться в екц"), # модели ЕКЦ
|
||||
("екц", "записаться в екц"),
|
||||
("minsoc", "какие выплаты"), # минсоц
|
||||
("техническая", "подключите оператора"), # техподдержка
|
||||
("тест", "тестовый запрос"),
|
||||
]
|
||||
```
|
||||
|
||||
## Шаг 2: Первый запуск без asserts
|
||||
|
||||
Запусти тест с `-v` (verbose), чтобы увидеть каждую модель и её ответ:
|
||||
|
||||
```bash
|
||||
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`:
|
||||
|
||||
```json
|
||||
{
|
||||
"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`:
|
||||
|
||||
```json
|
||||
{
|
||||
"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` для хеш-варианта или бэкапа, используй тот же текст, что для базовой модели. Разные тексты могут не работать для копий.
|
||||
|
||||
Пример:
|
||||
|
||||
```json
|
||||
// Базовая модель
|
||||
{"model": "zags", "text": "загс центрального района", "checks": {"min_found": 1}}
|
||||
|
||||
// Хеш-вариант — тот же текст!
|
||||
{"model": "zags~ffb403fff9f5802d53aac8a5c844af26", "text": "загс центрального района", "checks": {"min_found": 0}}
|
||||
```
|
||||
|
||||
## Шаг 4: Запуск с asserts
|
||||
|
||||
```bash
|
||||
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:
|
||||
```bash
|
||||
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`.
|
||||
|
||||
```bash
|
||||
# 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), гоняй тесты на каждой:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
@ -58,3 +58,7 @@ python3 test_smc_models.py --host 10.101.60.27 --port 6181
|
||||
- `text_contains` — подстрока в тексте/классе первой сущности
|
||||
- `calculated_contains` — подстрока в `calculated` (только entity)
|
||||
- `confidence_min` — минимальный confidence
|
||||
|
||||
## Как адаптировать под другой проект
|
||||
|
||||
См. [GUIDE.md](GUIDE.md) — полный гайд: от первого запуска до готового набора asserts.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user