универсальная версия: без хардкода имён моделей, pick_text по ключевым словам
This commit is contained in:
parent
9b78a5a1bb
commit
6e48b5da68
@ -1,6 +1,10 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""SEE model autotest — проверяет все загруженные модели после обновления.
|
"""SEE model autotest — проверяет все загруженные модели после обновления.
|
||||||
|
|
||||||
|
Универсальный: не содержит хардкода имён моделей, подходит для любой SEE-инсталляции.
|
||||||
|
Текст запроса подбирается динамически по имени модели.
|
||||||
|
Для точных проверок можно подключить asserts-файл.
|
||||||
|
|
||||||
Использование:
|
Использование:
|
||||||
python3 test_see_models.py
|
python3 test_see_models.py
|
||||||
python3 test_see_models.py --host 10.101.60.26
|
python3 test_see_models.py --host 10.101.60.26
|
||||||
@ -12,19 +16,12 @@
|
|||||||
"asserts": [
|
"asserts": [
|
||||||
{
|
{
|
||||||
"model": "fio", // подстрока для поиска модели
|
"model": "fio", // подстрока для поиска модели
|
||||||
"type": "entity|classifier",
|
"text": "Иванов Иван Иванович", // текст запроса (опционально)
|
||||||
"text": "Иванов Иван Иванович", // текст для запроса
|
|
||||||
"checks": {
|
"checks": {
|
||||||
// для entity:
|
"min_found": 1, // мин. количество сущностей/классов
|
||||||
"min_found": 1, // мин. количество найденных сущностей
|
"text_contains": "иван", // подстрока в text или class
|
||||||
"text_contains": "иванов", // подстрока в text первой сущности
|
|
||||||
"calculated_contains": "Ф:", // подстрока в calculated
|
"calculated_contains": "Ф:", // подстрока в calculated
|
||||||
"confidence_min": 0.5, // мин. confidence
|
"confidence_min": 0.5 // мин. confidence
|
||||||
|
|
||||||
// для classifier:
|
|
||||||
"min_classes": 1, // мин. количество классов
|
|
||||||
"top_class_contains": "Yes", // подстрока в top классе
|
|
||||||
"confidence_min": 0.5 // мин. confidence топ-класса
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -35,7 +32,6 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
@ -50,80 +46,74 @@ DEFAULT_HOST = "10.101.60.25"
|
|||||||
DEFAULT_PORT = 6184
|
DEFAULT_PORT = 6184
|
||||||
BASE_PATH = "/see"
|
BASE_PATH = "/see"
|
||||||
|
|
||||||
PRETRAINED_TESTS = {
|
TEXT_RULES = [
|
||||||
"fio": {"text": "Иванов Иван Иванович", "hint": "ФИО"},
|
# (keyword, text) — первое совпадение побеждает
|
||||||
"phone": {"text": "8 913 456 78 90", "hint": "телефон"},
|
|
||||||
"number": {"text": "пятьсот двадцать три", "hint": "число"},
|
|
||||||
"date": {"text": "на завтра", "hint": "дата"},
|
|
||||||
"uuid": {"text": "550e8400-e29b-41d4-a716-446655440000", "hint": "UUID"},
|
|
||||||
"time": {"text": "в пять часов вечера", "hint": "время"},
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLER_TESTS = {
|
|
||||||
"fio2": {"text": "Иванов Иван Иванович", "type": "entity"},
|
|
||||||
"phone2": {"text": "8 913 456 78 90", "type": "entity"},
|
|
||||||
"record_date": {"text": "на завтра", "type": "entity"},
|
|
||||||
"record_time": {"text": "в пять часов вечера", "type": "entity"},
|
|
||||||
"yesno": {"text": "да", "type": "classifier"},
|
|
||||||
"yesno_obzv": {"text": "да", "type": "classifier"},
|
|
||||||
"weekday": {"text": "в пятницу", "type": "classifier"},
|
|
||||||
"end_repeat": {"text": "все, до свидания", "type": "classifier"},
|
|
||||||
"operatorcheck": {"text": "соедините с оператором", "type": "classifier"},
|
|
||||||
"see_grade": {"text": "пять", "type": "classifier"},
|
|
||||||
"other_payment": {"text": "мобилизационные выплаты", "type": "classifier"},
|
|
||||||
"mobilizac": {"text": "мобилизационные", "type": "classifier"},
|
|
||||||
"matcap_direct": {"text": "на улучшение жилищных условий", "type": "classifier"},
|
|
||||||
"new_minsoc_subsidii": {"text": "субсидия на жкх", "type": "classifier"},
|
|
||||||
"new_trud": {"text": "потерял работу", "type": "classifier"},
|
|
||||||
"rating_med": {"text": "отлично", "type": "classifier"},
|
|
||||||
"zags": {"text": "загс центрального района", "type": "classifier"},
|
|
||||||
"zags_handler": {"text": "загс на нижегородской", "type": "classifier"},
|
|
||||||
"filial": {"text": "в мошковский филиал", "type": "classifier"},
|
|
||||||
"offices_mfc_see": {"text": "родники", "type": "classifier"},
|
|
||||||
"service_mfc_see": {"text": "хочу получить водительское удостоверение", "type": "classifier"},
|
|
||||||
"nsk_fillials": {"text": "в филиал на родниках", "type": "classifier"},
|
|
||||||
}
|
|
||||||
|
|
||||||
CUSTOM_MODEL_MATCHES = [
|
|
||||||
("record_date", "на завтра"),
|
|
||||||
("record_time", "в пять часов вечера"),
|
|
||||||
("fio", "Иванов Иван Иванович"),
|
("fio", "Иванов Иван Иванович"),
|
||||||
("phone", "8 913 456 78 90"),
|
("phone", "8 913 456 78 90"),
|
||||||
("date", "на завтра"),
|
|
||||||
("time", "в пять часов вечера"),
|
|
||||||
("uuid", "550e8400-e29b-41d4-a716-446655440000"),
|
|
||||||
("number", "пятьсот двадцать три"),
|
("number", "пятьсот двадцать три"),
|
||||||
("filial", "в филиал на родниках"),
|
("date", "на завтра"),
|
||||||
|
("record_date", "на завтра"),
|
||||||
|
("time", "в пять часов вечера"),
|
||||||
|
("record_time", "в пять часов вечера"),
|
||||||
|
("uuid", "550e8400-e29b-41d4-a716-446655440000"),
|
||||||
("zags", "загс центрального района"),
|
("zags", "загс центрального района"),
|
||||||
|
("nsk_fillials", "в филиал на родниках"),
|
||||||
|
("filial", "в филиал на родниках"),
|
||||||
|
("offices_mfc", "родники"),
|
||||||
|
("возраст", "мне 25 лет"),
|
||||||
|
("загран", "хочу загранпаспорт"),
|
||||||
("yesno", "да"),
|
("yesno", "да"),
|
||||||
("weekday", "в пятницу"),
|
("weekday", "в пятницу"),
|
||||||
("grade", "пять"),
|
("дни недели", "в пятницу"),
|
||||||
("obzv", "да"),
|
|
||||||
("operator", "соедините с оператором"),
|
("operator", "соедините с оператором"),
|
||||||
("repeat", "все, до свидания"),
|
("end_repeat", "все, до свидания"),
|
||||||
("matcap", "на улучшение жилищных условий"),
|
("повтор", "все, до свидания"),
|
||||||
|
("other_payment", "мобилизационные выплаты"),
|
||||||
|
("payment", "мобилизационные выплаты"),
|
||||||
("mobilizac", "мобилизационные"),
|
("mobilizac", "мобилизационные"),
|
||||||
("trud", "потерял работу"),
|
("trud", "потерял работу"),
|
||||||
("subsidii", "субсидия на жкх"),
|
("subsidii", "субсидия на жкх"),
|
||||||
("rating", "отлично"),
|
("minsoc", "субсидия на жкх"),
|
||||||
("payment", "мобилизационные выплаты"),
|
("matcap", "на улучшение жилищных условий"),
|
||||||
("service_mfc", "хочу получить паспорт"),
|
("маткап", "на улучшение жилищных условий"),
|
||||||
("offices_mfc", "родники"),
|
("паспорт", "хочу получить паспорт"),
|
||||||
("паспорт", "хочу получить загранпаспорт"),
|
("пособие", "пособие по рождению"),
|
||||||
("ЕПГУ", "проверить статус заявления на госуслугах"),
|
|
||||||
("лаврентьев", "как получить лаврентьевскую карту"),
|
|
||||||
("возраст", "мне 25 лет"),
|
|
||||||
("загран", "хочу сделать загранпаспорт"),
|
|
||||||
("вернуться", "вернуться в главное меню"),
|
|
||||||
("не знаю код", "не знаю код подразделения"),
|
|
||||||
("оценк", "оцениваю обслуживание на пять"),
|
|
||||||
("несогласи", "я не согласен с этим"),
|
|
||||||
("начало диалог", "здравствуйте"),
|
("начало диалог", "здравствуйте"),
|
||||||
("пособие", "какое пособие по рождению"),
|
("граждан", "я гражданин россии"),
|
||||||
("УК", "проблема с управляющей компанией"),
|
("выплат", "ежемесячные выплаты"),
|
||||||
|
("статус", "проверить статус заявления"),
|
||||||
|
("суперсервис", "рождение ребенка"),
|
||||||
|
("рождение", "рождение ребенка"),
|
||||||
|
("лаврентьев", "лаврентьевская карта"),
|
||||||
|
("несогласи", "я не согласен"),
|
||||||
|
("отказ", "отказываюсь"),
|
||||||
|
("оценк", "пять"),
|
||||||
|
("grade", "пять"),
|
||||||
|
("rating", "пять"),
|
||||||
|
("исключение", "это не относится"),
|
||||||
|
("режим", "режим работы мфц"),
|
||||||
|
("жкх", "режим работы мфц"),
|
||||||
|
("вернуться", "вернуться в главное меню"),
|
||||||
|
("не знаю", "не знаю код подразделения"),
|
||||||
|
("service_mfc", "хочу получить услугу"),
|
||||||
|
("service mfc", "хочу получить услугу"),
|
||||||
|
("mfc", "записаться в мфц"),
|
||||||
|
("мфц", "записаться в мфц"),
|
||||||
|
("тест", "тестовое сообщение"),
|
||||||
|
("test", "test message"),
|
||||||
|
("заглушк", "тестовый запрос"),
|
||||||
|
("stub", "test request"),
|
||||||
|
("конкретик", "конкретный вопрос"),
|
||||||
|
("да-нет", "да"),
|
||||||
]
|
]
|
||||||
|
|
||||||
FALLBACK_TEXT = "Здравствуйте, хочу записаться на приём в МФЦ для получения паспорта, запись на завтра"
|
|
||||||
|
def pick_text(model_id):
|
||||||
|
name_lower = model_id.lower()
|
||||||
|
for keyword, text in TEXT_RULES:
|
||||||
|
if keyword in name_lower:
|
||||||
|
return text
|
||||||
|
return "Здравствуйте, хочу записаться на приём в МФЦ"
|
||||||
|
|
||||||
|
|
||||||
def load_asserts(path):
|
def load_asserts(path):
|
||||||
@ -146,7 +136,7 @@ class SeeAPI:
|
|||||||
url = f"{self.base}/entities/{encoded}?text={quote(text)}&similarity={similarity}"
|
url = f"{self.base}/entities/{encoded}?text={quote(text)}&similarity={similarity}"
|
||||||
return json.loads(self._request(url))
|
return json.loads(self._request(url))
|
||||||
|
|
||||||
def _request(self, url, timeout=15):
|
def _request(self, url, timeout=30):
|
||||||
try:
|
try:
|
||||||
with urlreq.urlopen(url, timeout=timeout) as r:
|
with urlreq.urlopen(url, timeout=timeout) as r:
|
||||||
return r.read().decode("utf-8")
|
return r.read().decode("utf-8")
|
||||||
@ -163,10 +153,10 @@ class TestSeeModels(unittest.TestCase):
|
|||||||
cls.asserts = load_asserts(cls.args.asserts)
|
cls.asserts = load_asserts(cls.args.asserts)
|
||||||
data = cls.api.get_models()
|
data = cls.api.get_models()
|
||||||
TestSeeModels.models = data
|
TestSeeModels.models = data
|
||||||
total = len(data["models"]) + len(data["handlers"]) + len(data["pretrained"])
|
total = len(data.get("models", [])) + len(data.get("handlers", [])) + len(data.get("pretrained", []))
|
||||||
print(f"\n models: {len(data['models'])}, "
|
print(f"\n models: {len(data.get('models', []))}, "
|
||||||
f"handlers: {len(data['handlers'])}, "
|
f"handlers: {len(data.get('handlers', []))}, "
|
||||||
f"pretrained: {len(data['pretrained'])}")
|
f"pretrained: {len(data.get('pretrained', []))}")
|
||||||
if cls.asserts:
|
if cls.asserts:
|
||||||
print(f" asserts loaded: {len(cls.asserts)}")
|
print(f" asserts loaded: {len(cls.asserts)}")
|
||||||
if total == 0:
|
if total == 0:
|
||||||
@ -216,15 +206,6 @@ class TestSeeModels(unittest.TestCase):
|
|||||||
self.assertGreaterEqual(first.get("confidence", 0), checks["confidence_min"],
|
self.assertGreaterEqual(first.get("confidence", 0), checks["confidence_min"],
|
||||||
f"{model_id}: confidence < {checks['confidence_min']}")
|
f"{model_id}: confidence < {checks['confidence_min']}")
|
||||||
|
|
||||||
def _text_for_model(self, model_id):
|
|
||||||
a = self._find_assert(model_id)
|
|
||||||
if a and "text" in a:
|
|
||||||
return a["text"]
|
|
||||||
for substr, text in CUSTOM_MODEL_MATCHES:
|
|
||||||
if substr in model_id:
|
|
||||||
return text
|
|
||||||
return FALLBACK_TEXT
|
|
||||||
|
|
||||||
def _is_empty(self, result):
|
def _is_empty(self, result):
|
||||||
if not result or result == {}:
|
if not result or result == {}:
|
||||||
return True
|
return True
|
||||||
@ -232,13 +213,6 @@ class TestSeeModels(unittest.TestCase):
|
|||||||
isinstance(v, list) and len(v) == 0 for v in result.values()
|
isinstance(v, list) and len(v) == 0 for v in result.values()
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_01_list_models(self):
|
|
||||||
"""Получение списка моделей"""
|
|
||||||
data = self.models
|
|
||||||
self.assertIn("models", data)
|
|
||||||
self.assertIn("handlers", data)
|
|
||||||
self.assertIn("pretrained", data)
|
|
||||||
|
|
||||||
def _fmt_result(self, model_id, result):
|
def _fmt_result(self, model_id, result):
|
||||||
print(f" >> {model_id}")
|
print(f" >> {model_id}")
|
||||||
if isinstance(result, dict) and "classes" in result:
|
if isinstance(result, dict) and "classes" in result:
|
||||||
@ -257,64 +231,15 @@ class TestSeeModels(unittest.TestCase):
|
|||||||
if len(entities) > 3:
|
if len(entities) > 3:
|
||||||
print(f" ... ({len(entities)} entities)")
|
print(f" ... ({len(entities)} entities)")
|
||||||
|
|
||||||
def test_02_pretrained_models(self):
|
def _test_all_models(self, models, category):
|
||||||
"""Проверка pretrained-моделей"""
|
|
||||||
errors = []
|
errors = []
|
||||||
for model_id, td in PRETRAINED_TESTS.items():
|
for model_id in models:
|
||||||
if model_id not in self.models.get("pretrained", []):
|
if not model_id:
|
||||||
errors.append(f" {model_id}: нет в списке")
|
|
||||||
continue
|
continue
|
||||||
try:
|
text = pick_text(model_id)
|
||||||
result = self.api.test_entity(model_id, td["text"])
|
|
||||||
if self._is_empty(result):
|
|
||||||
errors.append(f" {model_id}: пустой результат")
|
|
||||||
else:
|
|
||||||
self._check_assert(model_id, result)
|
|
||||||
self._fmt_result(model_id, result)
|
|
||||||
except AssertionError:
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
errors.append(f" {model_id}: {e}")
|
|
||||||
if errors:
|
|
||||||
self.fail("Ошибки pretrained:\n" + "\n".join(errors))
|
|
||||||
|
|
||||||
def test_03_handler_models(self):
|
|
||||||
"""Проверка handler-моделей"""
|
|
||||||
errors = []
|
|
||||||
handlers = self.models.get("handlers", [])
|
|
||||||
if not handlers:
|
|
||||||
self.skipTest("Нет handler моделей")
|
|
||||||
for model_id in handlers:
|
|
||||||
text = FALLBACK_TEXT
|
|
||||||
for key, td in HANDLER_TESTS.items():
|
|
||||||
if key in model_id:
|
|
||||||
text = td["text"]
|
|
||||||
break
|
|
||||||
a = self._find_assert(model_id)
|
a = self._find_assert(model_id)
|
||||||
if a and "text" in a:
|
if a and "text" in a:
|
||||||
text = a["text"]
|
text = a["text"]
|
||||||
try:
|
|
||||||
result = self.api.test_entity(model_id, text)
|
|
||||||
if self._is_empty(result):
|
|
||||||
print(f" [!] {model_id}: пустой результат")
|
|
||||||
else:
|
|
||||||
self._check_assert(model_id, result)
|
|
||||||
self._fmt_result(model_id, result)
|
|
||||||
except AssertionError:
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
errors.append(f" {model_id}: {e}")
|
|
||||||
if errors:
|
|
||||||
self.fail("Ошибки handler:\n" + "\n".join(errors))
|
|
||||||
|
|
||||||
def test_04_custom_models(self):
|
|
||||||
"""Проверка кастомных моделей"""
|
|
||||||
errors = []
|
|
||||||
models = self.models.get("models", [])
|
|
||||||
if not models:
|
|
||||||
self.skipTest("Нет кастомных моделей")
|
|
||||||
for model_id in models:
|
|
||||||
text = self._text_for_model(model_id)
|
|
||||||
try:
|
try:
|
||||||
result = self.api.test_entity(model_id, text)
|
result = self.api.test_entity(model_id, text)
|
||||||
if self._is_empty(result):
|
if self._is_empty(result):
|
||||||
@ -326,35 +251,42 @@ class TestSeeModels(unittest.TestCase):
|
|||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append(f" {model_id}: {e}")
|
errors.append(f" {model_id}: {e}")
|
||||||
|
return errors
|
||||||
|
|
||||||
|
def test_01_list_models(self):
|
||||||
|
"""Получение списка моделей"""
|
||||||
|
data = self.models
|
||||||
|
self.assertIn("models", data)
|
||||||
|
self.assertIn("handlers", data)
|
||||||
|
self.assertIn("pretrained", data)
|
||||||
|
|
||||||
|
def test_02_pretrained_models(self):
|
||||||
|
"""Проверка pretrained-моделей"""
|
||||||
|
pretrained = self.models.get("pretrained", [])
|
||||||
|
if not pretrained:
|
||||||
|
self.skipTest("Нет pretrained моделей")
|
||||||
|
errors = self._test_all_models(pretrained, "pretrained")
|
||||||
|
if errors:
|
||||||
|
self.fail("Ошибки pretrained:\n" + "\n".join(errors))
|
||||||
|
|
||||||
|
def test_03_handler_models(self):
|
||||||
|
"""Проверка handler-моделей"""
|
||||||
|
handlers = self.models.get("handlers", [])
|
||||||
|
if not handlers:
|
||||||
|
self.skipTest("Нет handler моделей")
|
||||||
|
errors = self._test_all_models(handlers, "handler")
|
||||||
|
if errors:
|
||||||
|
self.fail("Ошибки handler:\n" + "\n".join(errors))
|
||||||
|
|
||||||
|
def test_04_custom_models(self):
|
||||||
|
"""Проверка кастомных моделей"""
|
||||||
|
models = self.models.get("models", [])
|
||||||
|
if not models:
|
||||||
|
self.skipTest("Нет кастомных моделей")
|
||||||
|
errors = self._test_all_models(models, "custom")
|
||||||
if errors:
|
if errors:
|
||||||
self.fail("Ошибки кастомных моделей:\n" + "\n".join(errors))
|
self.fail("Ошибки кастомных моделей:\n" + "\n".join(errors))
|
||||||
|
|
||||||
def test_05_handler_pretrained_coverage(self):
|
|
||||||
"""Проверка handler моделей phone/uuid/number/fio"""
|
|
||||||
errors = []
|
|
||||||
handlers = self.models.get("handlers", [])
|
|
||||||
for htype, td in [("phone", PRETRAINED_TESTS["phone"]),
|
|
||||||
("uuid", PRETRAINED_TESTS["uuid"]),
|
|
||||||
("number", PRETRAINED_TESTS["number"]),
|
|
||||||
("fio", PRETRAINED_TESTS["fio"])]:
|
|
||||||
matching = [h for h in handlers if htype in h.lower()]
|
|
||||||
if not matching:
|
|
||||||
continue
|
|
||||||
for mid in matching[:2]:
|
|
||||||
try:
|
|
||||||
result = self.api.test_entity(mid, td["text"])
|
|
||||||
if self._is_empty(result):
|
|
||||||
print(f" [!] {mid} ({td['hint']})")
|
|
||||||
else:
|
|
||||||
self._check_assert(mid, result)
|
|
||||||
self._fmt_result(mid, result)
|
|
||||||
except AssertionError:
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
errors.append(f" {mid}: {e}")
|
|
||||||
if errors:
|
|
||||||
self.fail("Ошибки handler coverage:\n" + "\n".join(errors))
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="SEE model autotest")
|
parser = argparse.ArgumentParser(description="SEE model autotest")
|
||||||
|
|||||||
@ -11,12 +11,11 @@
|
|||||||
{
|
{
|
||||||
"asserts": [
|
"asserts": [
|
||||||
{
|
{
|
||||||
"model": "МФЦ НСК", // подстрока для поиска модели
|
"model": "МФЦ НСК",
|
||||||
"type": "classifier",
|
|
||||||
"text": "записаться на приём", // опционально, свой текст
|
"text": "записаться на приём", // опционально, свой текст
|
||||||
"checks": {
|
"checks": {
|
||||||
"min_classes": 1, // мин. количество классов
|
"min_found": 1, // мин. количество классов
|
||||||
"top_class_contains": "МФЦ", // подстрока в top классе
|
"text_contains": "Запись", // подстрока в top классе
|
||||||
"confidence_min": 0.5 // мин. confidence топ-класса
|
"confidence_min": 0.5 // мин. confidence топ-класса
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,7 +41,28 @@ DEFAULT_HOST = "10.101.60.27"
|
|||||||
DEFAULT_PORT = 6181
|
DEFAULT_PORT = 6181
|
||||||
BASE_PATH = "/smc"
|
BASE_PATH = "/smc"
|
||||||
|
|
||||||
DEFAULT_TEXT = "Здравствуйте, хочу записаться на приём в МФЦ для получения паспорта"
|
TEXT_RULES = [
|
||||||
|
("мфц", "записаться в мфц"),
|
||||||
|
("mfc", "записаться в мфц"),
|
||||||
|
("филиал", "какой филиал работает"),
|
||||||
|
("ekc", "записаться в екц"),
|
||||||
|
("екц", "записаться в екц"),
|
||||||
|
("minsoc", "какие выплаты"),
|
||||||
|
("минсоц", "какие выплаты"),
|
||||||
|
("техническая", "не работает сайт"),
|
||||||
|
("поддержка", "не работает сайт"),
|
||||||
|
("offices", "какие офисы работают"),
|
||||||
|
("тест", "тестовый запрос"),
|
||||||
|
("test", "test query"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def pick_text(model_id):
|
||||||
|
name_lower = model_id.lower()
|
||||||
|
for keyword, text in TEXT_RULES:
|
||||||
|
if keyword in name_lower:
|
||||||
|
return text
|
||||||
|
return "Здравствуйте, хочу записаться на приём"
|
||||||
|
|
||||||
|
|
||||||
def load_asserts(path):
|
def load_asserts(path):
|
||||||
@ -124,7 +144,7 @@ class TestSmcModels(unittest.TestCase):
|
|||||||
for mid in models:
|
for mid in models:
|
||||||
if not mid:
|
if not mid:
|
||||||
continue
|
continue
|
||||||
text = DEFAULT_TEXT
|
text = pick_text(mid)
|
||||||
a = self._find_assert(mid)
|
a = self._find_assert(mid)
|
||||||
if a and "text" in a:
|
if a and "text" in a:
|
||||||
text = a["text"]
|
text = a["text"]
|
||||||
@ -158,7 +178,7 @@ class TestSmcModels(unittest.TestCase):
|
|||||||
for mid in handlers:
|
for mid in handlers:
|
||||||
if not mid:
|
if not mid:
|
||||||
continue
|
continue
|
||||||
text = DEFAULT_TEXT
|
text = pick_text(mid)
|
||||||
a = self._find_assert(mid)
|
a = self._find_assert(mid)
|
||||||
if a and "text" in a:
|
if a and "text" in a:
|
||||||
text = a["text"]
|
text = a["text"]
|
||||||
@ -181,7 +201,7 @@ class TestSmcModels(unittest.TestCase):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append(f" {mid}: {e}")
|
errors.append(f" {mid}: {e}")
|
||||||
if errors:
|
if errors:
|
||||||
self.fail("Ошибки internal:\n" + "\n".join(errors))
|
self.fail("Ошибки handler:\n" + "\n".join(errors))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user