lazier

personal summarizer
Log | Files | Refs | README

test_chapters.py (3127B)


      1 """Testes do gerador de capitulos."""
      2 
      3 from __future__ import annotations
      4 
      5 import json
      6 import os
      7 import unittest
      8 from types import SimpleNamespace
      9 from unittest.mock import MagicMock, patch
     10 
     11 from lazier.core.chapters import build_chapters
     12 from lazier.core.config import reset_model_config_cache
     13 
     14 
     15 class _FakeChoice:
     16     def __init__(self, content: str) -> None:
     17         self.message = SimpleNamespace(content=content)
     18 
     19 
     20 class _FakeResponse:
     21     def __init__(self, content: str) -> None:
     22         self.choices = [_FakeChoice(content)]
     23 
     24 
     25 def _segments(count: int, step: float = 5.0):
     26     """Gera segments simples com timestamps incrementais."""
     27     return [
     28         {
     29             "start": i * step,
     30             "end": (i + 1) * step,
     31             "text": f"trecho {i + 1}",
     32         }
     33         for i in range(count)
     34     ]
     35 
     36 
     37 class ChaptersTests(unittest.TestCase):
     38     def setUp(self) -> None:
     39         os.environ["OPENAI_API_KEY"] = "test-key"
     40         os.environ.pop("OPENAI_REASONING_EFFORT", None)
     41         reset_model_config_cache()
     42 
     43     def tearDown(self) -> None:
     44         reset_model_config_cache()
     45 
     46     def test_returns_empty_when_no_segments(self):
     47         self.assertEqual(build_chapters([]), [])
     48 
     49     def test_uses_fallback_for_short_audio(self):
     50         # Menos que MIN_SEGMENTS_FOR_CHAPTERS (6) -> fallback determinista.
     51         result = build_chapters(_segments(3))
     52         self.assertEqual(len(result), 1)
     53         self.assertEqual(result[0]["start"], 0.0)
     54         self.assertGreater(result[0]["end"], 0.0)
     55         self.assertIn("start_hms", result[0])
     56 
     57     def test_builds_chapters_from_llm_response(self):
     58         segments = _segments(20, step=10.0)  # 0..200s
     59         llm_payload = {
     60             "chapters": [
     61                 {"title": "Intro", "summary": "Abertura.", "start_index": 0, "end_index": 4},
     62                 {"title": "Core", "summary": "Conteudo principal.", "start_index": 5, "end_index": 14},
     63                 {"title": "Wrap", "summary": "Fechamento.", "start_index": 15, "end_index": 19},
     64             ]
     65         }
     66 
     67         client = MagicMock()
     68         client.chat.completions.create.return_value = _FakeResponse(json.dumps(llm_payload))
     69 
     70         with patch("lazier.core.chapters._ensure_client", return_value=client):
     71             chapters = build_chapters(segments, model="gpt-4o-mini")
     72 
     73         self.assertEqual(len(chapters), 3)
     74         self.assertEqual(chapters[0]["title"], "Intro")
     75         self.assertEqual(chapters[0]["start"], 0.0)
     76         self.assertGreaterEqual(chapters[1]["start"], chapters[0]["end"])
     77         self.assertEqual(chapters[2]["title"], "Wrap")
     78 
     79     def test_falls_back_when_llm_fails(self):
     80         segments = _segments(10, step=6.0)
     81         client = MagicMock()
     82         client.chat.completions.create.side_effect = Exception("network down")
     83 
     84         with patch("lazier.core.chapters._ensure_client", return_value=client):
     85             chapters = build_chapters(segments)
     86 
     87         self.assertGreaterEqual(len(chapters), 1)
     88         self.assertEqual(chapters[0]["start"], 0.0)
     89         self.assertEqual(chapters[0]["title"], "Parte 1")
     90 
     91 
     92 if __name__ == "__main__":
     93     unittest.main()