Просмотр исходного кода

test(movie): keep tool output out of the test log

The in-process narration and subtitle tests let the tools' stdout and
stderr through to the runner. Capture both and assert the expected
diagnostics.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Drew Ritter 2 недель назад
Родитель
Сommit
4f5304bd31

+ 17 - 5
tests/proving-it-works-with-a-movie/test_narration.py

@@ -1,4 +1,6 @@
+import io
 import tempfile
+from contextlib import redirect_stderr, redirect_stdout
 import unittest
 from pathlib import Path
 from unittest.mock import patch
@@ -76,11 +78,15 @@ class NarrationDriftRegression(unittest.TestCase):
             ]}), encoding="utf-8")
             argv = ["narrate", str(scenes), str(output),
                     "--engine", "piper", "--verify", "on"]
+            stdout, stderr = io.StringIO(), io.StringIO()
             with patch.object(sys, "argv", argv), \
                  patch.object(module, "openai_key", return_value=None), \
                  patch.object(module, "duration", return_value=1.0), \
-                 patch.object(module, "transcribe_local", return_value=None):
+                 patch.object(module, "transcribe_local", return_value=None), \
+                 redirect_stdout(stdout), redirect_stderr(stderr):
                 self.assertNotEqual(module.main(), 0)
+            self.assertIn("clip: required verification unavailable", stderr.getvalue())
+            self.assertIn("FAILED verbatim delivery: ['clip']", stderr.getvalue())
 
 class TranscriptionProtocolRegression(unittest.TestCase):
     def test_owned_json_is_used_instead_of_library_stdout(self):
@@ -88,7 +94,6 @@ class TranscriptionProtocolRegression(unittest.TestCase):
         import subprocess
         import sys
         import io
-        from contextlib import redirect_stderr
         module = fixtures.load_script("narrate")
         def child(argv, **kwargs):
             self.assertIn("--isolated", argv)
@@ -113,8 +118,11 @@ class TranscriptionProtocolRegression(unittest.TestCase):
                     if payload is not None and "--isolated" in argv:
                         Path(argv[-1]).write_text(payload, encoding="utf-8")
                     return subprocess.CompletedProcess(argv, code, "misleading stdout", "error")
-                with patch.object(module.subprocess, "run", side_effect=child):
+                diagnostics = io.StringIO()
+                with patch.object(module.subprocess, "run", side_effect=child), \
+                     redirect_stderr(diagnostics):
                     self.assertIsNone(module.transcribe_local(Path("clip.wav")))
+                self.assertIn("local ASR", diagnostics.getvalue())
 
     def test_fresh_and_off_then_on_clips_require_asr(self):
         import json
@@ -131,10 +139,14 @@ class TranscriptionProtocolRegression(unittest.TestCase):
                 argv = ["narrate", str(scenes), str(output), "--engine", "piper", "--verify"]
                 with patch.object(module, "openai_key", return_value=None), patch.object(module, "say_piper", side_effect=synthesize), patch.object(module, "duration", return_value=1.0), patch.object(module, "transcribe_local", return_value=None):
                     if cached:
-                        with patch.object(sys, "argv", [*argv, "off"]):
+                        with patch.object(sys, "argv", [*argv, "off"]), \
+                             redirect_stdout(io.StringIO()), redirect_stderr(io.StringIO()):
                             self.assertEqual(module.main(), 0)
-                    with patch.object(sys, "argv", [*argv, "on"]):
+                    stdout, stderr = io.StringIO(), io.StringIO()
+                    with patch.object(sys, "argv", [*argv, "on"]), \
+                         redirect_stdout(stdout), redirect_stderr(stderr):
                         self.assertNotEqual(module.main(), 0)
+                    self.assertIn("clip: required verification unavailable", stderr.getvalue())
 
 
 if __name__ == "__main__":

+ 6 - 2
tests/proving-it-works-with-a-movie/test_subtitles.py

@@ -27,8 +27,10 @@ class SubtitlePathRegression(unittest.TestCase):
                     self.assertEqual((cwd / "captions.srt").read_bytes(), subs.read_bytes())
                 return True
 
-            with patch.object(sys, "argv", ["burn-subtitles", str(movie), str(subs), str(output)]), patch.object(module, "has_libass", return_value=True), patch.object(module, "run", side_effect=fake_run):
+            stdout, stderr = io.StringIO(), io.StringIO()
+            with patch.object(sys, "argv", ["burn-subtitles", str(movie), str(subs), str(output)]), patch.object(module, "has_libass", return_value=True), patch.object(module, "run", side_effect=fake_run), redirect_stdout(stdout), redirect_stderr(stderr):
                 self.assertEqual(module.main(), 0)
+            self.assertIn("burned into the picture", stdout.getvalue())
             command, cwd = calls[0]
             self.assertEqual(cwd.name.startswith("movie-subtitles-"), True)
             self.assertIn(str(movie.resolve()), command)
@@ -43,8 +45,10 @@ class SubtitlePathRegression(unittest.TestCase):
             movie, subs, output = root / "in.mp4", root / "captions.srt", root / "out.mp4"
             movie.write_bytes(b"movie")
             subs.write_text("1\n00:00:00,000 --> 00:00:01,000\ncaption\n", encoding="utf-8")
-            with patch.object(sys, "argv", ["burn-subtitles", str(movie), str(subs), str(output)]), patch.object(module, "has_libass", return_value=True), patch.object(module, "run", return_value=False):
+            stdout, stderr = io.StringIO(), io.StringIO()
+            with patch.object(sys, "argv", ["burn-subtitles", str(movie), str(subs), str(output)]), patch.object(module, "has_libass", return_value=True), patch.object(module, "run", return_value=False), redirect_stdout(stdout), redirect_stderr(stderr):
                 self.assertEqual(module.main(), 1)
+            self.assertIn("burn failed", stderr.getvalue())
 
 class SubtitleIntegrationRegression(unittest.TestCase):
     def test_bom_manifest_and_offsets_write_utf8_under_legacy_console(self):