diff options
| author | historia <historiavg@proton.me> | 2026-08-30 18:49:32 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-30 18:49:32 -0400 |
| commit | 93f106aac2d6411c80a911adac62cd12f80e58be (patch) | |
| tree | 5db8a2ff27f0d06ef313b3cf9ab84bf02f74479f /app/tests/test_audiobook_cli.py | |
| parent | d31e9149c7f141b2d3c14a79e9f067d524c8c420 (diff) | |
| download | tts-audiobook-generator-93f106aac2d6411c80a911adac62cd12f80e58be.tar.gz | |
feat: output log path when audiobook generation fails
Diffstat (limited to 'app/tests/test_audiobook_cli.py')
| -rw-r--r-- | app/tests/test_audiobook_cli.py | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/app/tests/test_audiobook_cli.py b/app/tests/test_audiobook_cli.py index f13cf9e..a3f0b90 100644 --- a/app/tests/test_audiobook_cli.py +++ b/app/tests/test_audiobook_cli.py @@ -26,6 +26,7 @@ if str(REPO_ROOT) not in sys.path: sys.path.insert(0, str(REPO_ROOT)) import audiobook # noqa: E402 +import logging_kit # noqa: E402 from converter import config # noqa: E402 from converter import converter as converter_mod # noqa: E402 from converter.converter import AudiobookConverter # noqa: E402 @@ -565,6 +566,10 @@ class FatalErrorReportingTests(unittest.TestCase): (log_path,) = self.log_dir.glob("audiobook_*.log") return log_path.read_text(encoding="utf-8") + def _log_path(self) -> str: + """The dated log file's full path, as the console reports it.""" + return str(logging_kit.stream_path("audiobook", self.log_dir)) + def test_expected_failure_shows_one_friendly_line(self): message = ("The audio.cpp model 'Qwen3-TTS-12Hz-1.7B-Base-GGUF' " "(family 'qwen3_tts') has no built-in speakers " @@ -573,6 +578,8 @@ class FatalErrorReportingTests(unittest.TestCase): self.assertEqual(code, 1) self.assertEqual(out.count("[FATAL]"), 1) self.assertIn(f"[FATAL] Fatal error: {message}", out) + self.assertIn(f"[INFO] Full details in the log file: " + f"{self._log_path()}", out) self.assertNotIn("Traceback (most recent call last)", out) self.assertNotIn("Traceback (most recent call last)", err) log_text = self._log_text() @@ -581,11 +588,14 @@ class FatalErrorReportingTests(unittest.TestCase): def test_expected_failure_reports_error_event(self): events = [] - code, _, _ = self._convert(ValueError("bad input"), - progress=events.append) + code, out, _ = self._convert(ValueError("bad input"), + progress=events.append) self.assertEqual(code, 1) self.assertEqual(events, [{"kind": "error", "message": "bad input"}]) + # The TUI run view owns the console and points failures at the log + # itself; no console pointer on this path. + self.assertNotIn("Full details in the log file", out) def test_unexpected_crash_also_shows_traceback(self): code, out, err = self._convert(TypeError("boom")) @@ -594,6 +604,26 @@ class FatalErrorReportingTests(unittest.TestCase): self.assertIn("Traceback (most recent call last)", err) self.assertIn("TypeError: boom", err) self.assertIn("Traceback (most recent call last)", self._log_text()) + self.assertIn(f"[INFO] Full details in the log file: " + f"{self._log_path()}", out) + + def test_failed_run_prints_the_log_path(self): + # A run that fails without raising (a book aborted the rest) ends + # with the log file path too. + preflight = MagicMock( + return_value=([self.book], [(self.book, "dune")])) + fake_class = MagicMock() + fake_class.preflight_overwrites = preflight + fake_class.return_value.run.return_value = False + out, err = io.StringIO(), io.StringIO() + with patch.object(audiobook, "setup_directories"), \ + contextlib.redirect_stdout(out), \ + contextlib.redirect_stderr(err), \ + patch.object(audiobook, "AudiobookConverter", fake_class): + code = audiobook.convert(backend="audiocpp") + self.assertEqual(code, 1) + self.assertIn(f"[INFO] Full details in the log file: " + f"{self._log_path()}", out.getvalue()) if __name__ == "__main__": |
