"""Тесты `QwenTokenCounter`: ленивая загрузка токенизатора и фолбэк-эвристика.""" import logging from pathlib import Path import pytest from core.summarization.tokens import QwenTokenCounter def test_no_tokenizer_path_falls_back_to_heuristic() -> None: """Без пути к токенизатору — эвристика `len(text) // 3`.""" counter = QwenTokenCounter(tokenizer_path=None) assert counter("а" * 30) == 10 def test_missing_tokenizer_file_falls_back_to_heuristic( tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Несуществующий файл токенизатора → фолбэк без падения, с warning в лог.""" missing_path = str(tmp_path / "does-not-exist" / "tokenizer.json") counter = QwenTokenCounter(tokenizer_path=missing_path) with caplog.at_level(logging.WARNING): result = counter("абвгдеёжз" * 3) assert result == len("абвгдеёжз" * 3) // 3 assert any("токенизатор" in record.message.lower() for record in caplog.records) def test_corrupted_tokenizer_file_falls_back_to_heuristic( tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Битый JSON токенизатора → фолбэк без падения, с warning в лог.""" bad_file = tmp_path / "tokenizer.json" bad_file.write_text("это не валидный json токенизатора") counter = QwenTokenCounter(tokenizer_path=str(bad_file)) with caplog.at_level(logging.WARNING): result = counter("текст для проверки") assert result == len("текст для проверки") // 3 assert any("токенизатор" in record.message.lower() for record in caplog.records) def test_loading_is_lazy_and_cached() -> None: """Токенизатор не загружается при инстанцировании, попытка загрузки — один раз.""" counter = QwenTokenCounter(tokenizer_path=None) assert counter._load_attempted is False counter("тест") assert counter._load_attempted is True counter("ещё один вызов") # не должно повторно пытаться грузить/падать