Spaces:
Running
Running
SilverElixir commited on
Commit ·
fd5cff9
1
Parent(s): 32db59b
Drop 4 duplicate and introspection-only tests
Browse files- tests/test_bot_routes.py +0 -22
- tests/test_bot_state.py +0 -7
- tests/test_lumen_formatting.py +1 -17
tests/test_bot_routes.py
CHANGED
|
@@ -556,28 +556,6 @@ def test_ask_gemini_attempt_respects_short_budget(monkeypatch):
|
|
| 556 |
bot.chat_state.pop(chat_id, None)
|
| 557 |
|
| 558 |
|
| 559 |
-
def test_gemini_spent_budget_does_not_pretend_blocked(monkeypatch):
|
| 560 |
-
# Регрессия (враждебное ревью 27.09.2026): когда повтор после битого вызова не
|
| 561 |
-
# влезал в бюджет, функция возвращала непустую строку "[Ответ заблокирован...]",
|
| 562 |
-
# ask_gemini считал её успехом и юзер получал её вместо ответа следующей модели.
|
| 563 |
-
async def must_not_run(*, model, contents, config=None):
|
| 564 |
-
raise AssertionError("retry must not run on a spent budget")
|
| 565 |
-
|
| 566 |
-
fake_client = MagicMock()
|
| 567 |
-
fake_client.aio.models.generate_content = must_not_run
|
| 568 |
-
original_client = bot.client
|
| 569 |
-
bot.client = fake_client
|
| 570 |
-
try:
|
| 571 |
-
resp = _FakeGeminiResponse(text="", candidates=[_FakeCandidate(finish_reason="MALFORMED_FUNCTION_CALL")])
|
| 572 |
-
ans = asyncio.run(bot._extract_gemini_answer_text(
|
| 573 |
-
resp, model_id="gemini-3.8-flash", call_contents=[], gconfig=None,
|
| 574 |
-
deadline=time.monotonic() - 1.0,
|
| 575 |
-
))
|
| 576 |
-
assert ans == "", "пустой ответ должен уводить маршрут на следующую модель"
|
| 577 |
-
finally:
|
| 578 |
-
bot.client = original_client
|
| 579 |
-
|
| 580 |
-
|
| 581 |
def test_is_gemini_daily_quota_recognizes_google_per_day_metric():
|
| 582 |
# Google пишет суточную квоту слитно в имени метрики
|
| 583 |
# (GenerateRequestsPerDayPerProjectPerModel) — без токена perday она
|
|
|
|
| 556 |
bot.chat_state.pop(chat_id, None)
|
| 557 |
|
| 558 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 559 |
def test_is_gemini_daily_quota_recognizes_google_per_day_metric():
|
| 560 |
# Google пишет суточную квоту слитно в имени метрики
|
| 561 |
# (GenerateRequestsPerDayPerProjectPerModel) — без токена perday она
|
tests/test_bot_state.py
CHANGED
|
@@ -50,13 +50,6 @@ def test_split_text_chunks_preserves_all_words():
|
|
| 50 |
assert " ".join(chunks).split() == text.split()
|
| 51 |
|
| 52 |
|
| 53 |
-
def test_split_text_chunks_lives_in_formatting_module():
|
| 54 |
-
# Срез монолита (сентябрь 2026): реализация — в lumen_formatting, bot.py
|
| 55 |
-
# только ре-экспортирует имя, чтобы bot._split_text_chunks работал как раньше.
|
| 56 |
-
import lumen_formatting
|
| 57 |
-
assert bot._split_text_chunks is lumen_formatting._split_text_chunks
|
| 58 |
-
|
| 59 |
-
|
| 60 |
def test_sanitize_mime_type_guesses_from_extension():
|
| 61 |
assert bot._sanitize_mime_type("photo.jpg", "") == "image/jpeg"
|
| 62 |
|
|
|
|
| 50 |
assert " ".join(chunks).split() == text.split()
|
| 51 |
|
| 52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
def test_sanitize_mime_type_guesses_from_extension():
|
| 54 |
assert bot._sanitize_mime_type("photo.jpg", "") == "image/jpeg"
|
| 55 |
|
tests/test_lumen_formatting.py
CHANGED
|
@@ -14,10 +14,7 @@ Telegram/Gemini/OpenRouter/рантайм-состояния бота, поэт
|
|
| 14 |
Запуск:
|
| 15 |
pytest test_lumen_formatting.py -v
|
| 16 |
"""
|
| 17 |
-
import inspect
|
| 18 |
-
|
| 19 |
import lumen_formatting
|
| 20 |
-
import lumen_streaming
|
| 21 |
|
| 22 |
|
| 23 |
|
|
@@ -421,15 +418,6 @@ def test_render_paths_differ_only_for_headings():
|
|
| 421 |
assert lumen_formatting._md_to_rich_html("## Title") == "<h3>Title</h3>"
|
| 422 |
|
| 423 |
|
| 424 |
-
def test_streaming_history_uses_summarizing_trim():
|
| 425 |
-
# Стриминговый путь резал историю голым del, из-за чего саммаризация старого
|
| 426 |
-
# работала только в нестриминговых ветках (аудит 26.09.2026).
|
| 427 |
-
src = inspect.getsource(lumen_streaming._run_streaming_reply)
|
| 428 |
-
code_lines = [ln for ln in src.splitlines() if not ln.strip().startswith("#")]
|
| 429 |
-
assert any("_trim_history" in ln for ln in code_lines)
|
| 430 |
-
assert not any("hist[:-" in ln for ln in code_lines), "в стриминге остался молчаливый срез истории"
|
| 431 |
-
|
| 432 |
-
|
| 433 |
def test_md_to_rich_html_splits_three_bullets_prod_movies():
|
| 434 |
# Прод 26.09.2026: ответ про мелодрамы — 3 пункта склеились, rich-путь молчал.
|
| 435 |
text = (
|
|
@@ -513,11 +501,7 @@ def test_md_to_html_strips_literal_span_spoiler_tag():
|
|
| 513 |
|
| 514 |
|
| 515 |
# ─────────────────── подсветка синтаксиса: язык из ```fence сохраняется ───────────────────
|
| 516 |
-
|
| 517 |
-
def test_md_to_html_code_block_preserves_language_for_syntax_highlighting():
|
| 518 |
-
result = lumen_formatting._md_to_html("```python\nprint(1)\n```")
|
| 519 |
-
assert result == '<pre><code class="language-python">print(1)</code></pre>'
|
| 520 |
-
|
| 521 |
|
| 522 |
def test_md_to_html_code_block_without_language_unchanged():
|
| 523 |
assert lumen_formatting._md_to_html("```\nprint(1)\n```") == "<pre>print(1)</pre>"
|
|
|
|
| 14 |
Запуск:
|
| 15 |
pytest test_lumen_formatting.py -v
|
| 16 |
"""
|
|
|
|
|
|
|
| 17 |
import lumen_formatting
|
|
|
|
| 18 |
|
| 19 |
|
| 20 |
|
|
|
|
| 418 |
assert lumen_formatting._md_to_rich_html("## Title") == "<h3>Title</h3>"
|
| 419 |
|
| 420 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
def test_md_to_rich_html_splits_three_bullets_prod_movies():
|
| 422 |
# Прод 26.09.2026: ответ про мелодрамы — 3 пункта склеились, rich-путь молчал.
|
| 423 |
text = (
|
|
|
|
| 501 |
|
| 502 |
|
| 503 |
# ─────────────────── подсветка синтаксиса: язык из ```fence сохраняется ───────────────────
|
| 504 |
+
# (сам кейс с языком покрыт test_md_to_html_code_block выше)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 505 |
|
| 506 |
def test_md_to_html_code_block_without_language_unchanged():
|
| 507 |
assert lumen_formatting._md_to_html("```\nprint(1)\n```") == "<pre>print(1)</pre>"
|