Ru2SQL / tests /test_vocabulary.py
Tyycha's picture
fix bugs
cc2ed2f
"""Тесты на BusinessVocabulary (раздел 3.6 пояснительной записки)."""
from pathlib import Path
import pytest
from src.business.vocabulary import BusinessVocabulary
# ──────────────────────────────────────────────────────────────────────
# Загрузка
# ──────────────────────────────────────────────────────────────────────
def test_empty_vocabulary_is_falsy():
vocab = BusinessVocabulary.empty()
assert not vocab
assert vocab.render_system_context() == ""
def test_from_dict_basic():
vocab = BusinessVocabulary.from_dict(
{
"company": "ООО Тест",
"terms": {"выручка": "SUM(amount)"},
"filters": {"paid": "status='paid'"},
"notes": ["Период: 2025-01-01—2026-04-30"],
}
)
assert bool(vocab)
assert vocab.company == "ООО Тест"
assert vocab.terms == {"выручка": "SUM(amount)"}
assert vocab.filters == {"paid": "status='paid'"}
assert vocab.notes == ["Период: 2025-01-01—2026-04-30"]
def test_from_yaml_roundtrip(tmp_path: Path):
original = BusinessVocabulary(
company="ООО Ромашка",
terms={"выручка": "SUM(orders.amount)"},
filters={"paid_only": "orders.status='paid'"},
notes=["amount только в orders"],
)
path = tmp_path / "vocab.yaml"
original.save_yaml(path)
loaded = BusinessVocabulary.from_yaml(path)
assert loaded.company == original.company
assert loaded.terms == original.terms
assert loaded.filters == original.filters
assert loaded.notes == original.notes
def test_from_yaml_missing_file(tmp_path: Path):
with pytest.raises(FileNotFoundError):
BusinessVocabulary.from_yaml(tmp_path / "does_not_exist.yaml")
# ──────────────────────────────────────────────────────────────────────
# enrich_prompt — обратная совместимость со старым Streamlit-кодом
# ──────────────────────────────────────────────────────────────────────
def test_enrich_prompt_pass_through_when_empty():
vocab = BusinessVocabulary.empty()
assert vocab.enrich_prompt("Какая выручка?") == "Какая выручка?"
def test_enrich_prompt_adds_term_definition():
vocab = BusinessVocabulary(
terms={"выручка": "SUM(amount) WHERE status='paid'"},
)
enriched = vocab.enrich_prompt("Какая выручка за январь?")
assert "выручка" in enriched
assert "SUM(amount)" in enriched
assert "Какая выручка за январь?" in enriched
def test_enrich_prompt_case_insensitive_match():
vocab = BusinessVocabulary(terms={"выручка": "SUM(amount)"})
enriched = vocab.enrich_prompt("ВЫРУЧКА в этом месяце?")
assert "SUM(amount)" in enriched
def test_enrich_prompt_ignores_unrelated_terms():
vocab = BusinessVocabulary(
terms={
"выручка": "SUM(amount)",
"топ клиентов": "ORDER BY SUM(amount) DESC",
},
)
enriched = vocab.enrich_prompt("Какая выручка?")
# Релевантный термин подмешан, посторонний — нет
assert "SUM(amount)" in enriched
assert "ORDER BY SUM(amount) DESC" not in enriched
# ──────────────────────────────────────────────────────────────────────
# render_system_context — то, что подмешивается в system-сообщение
# ──────────────────────────────────────────────────────────────────────
def test_render_system_context_empty():
assert BusinessVocabulary.empty().render_system_context() == ""
def test_render_system_context_with_company():
vocab = BusinessVocabulary(
company="ООО Ромашка",
terms={"выручка": "SUM(amount)"},
)
ctx = vocab.render_system_context()
assert "ООО Ромашка" in ctx
assert "выручка" in ctx
assert "SUM(amount)" in ctx
def test_render_system_context_with_filters_and_notes():
vocab = BusinessVocabulary(
filters={"только_оплаченные": "orders.status='paid'"},
notes=["amount только в orders"],
)
ctx = vocab.render_system_context()
assert "только_оплаченные" in ctx
assert "orders.status='paid'" in ctx
assert "amount только в orders" in ctx