youtube_abschrift_korrigieren/tests/test_extract_text.py
dschlueter 19b6bbf5a2 feat: extract_text.py --fliesstext für lesbaren Fließtext
Umbruch auf 80 Zeichen ohne Worttrennung, auch nicht am Bindestrich.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:53:42 +02:00

112 lines
4.1 KiB
Python

"""Tests for extract_text.py; yt-dlp is always replaced by fakes (no network)."""
import sys
import pytest
import extract_text
import yt_untertitel as yt
URL = "https://www.youtube.com/watch?v=abc123"
VTT = (
"WEBVTT\n\n"
"00:00:01.000 --> 00:00:02.000\n \nGuten<00:00:01.500><c> Abend.</c>\n\n"
"00:00:02.000 --> 00:00:03.000\nGuten Abend.\nSchön, dass Sie da sind.\n"
)
GERMAN_VIDEO = {
"id": "abc123",
"title": "Eine Rede",
"subtitles": {"en": []},
"automatic_captions": {"de-orig": [], "de": [], "en": []},
}
pytestmark = pytest.mark.usefixtures("yt_dlp_installed")
def run_main(monkeypatch, *args):
monkeypatch.setattr(sys, "argv", ["extract_text.py", *map(str, args)])
extract_text.main()
def test_default_language_is_original_audio(fake_yt_dlp, tmp_path, monkeypatch, capsys):
run = fake_yt_dlp(GERMAN_VIDEO, vtt=VTT)
monkeypatch.setattr(yt.subprocess, "run", run)
monkeypatch.chdir(tmp_path)
run_main(monkeypatch, "-u", URL)
text = (tmp_path / "output.txt").read_text(encoding="utf-8")
assert text == "Guten Abend.\nSchön, dass Sie da sind.\n"
assert "de-orig" in run.calls[1]
assert "--write-auto-subs" in run.calls[1]
out = capsys.readouterr().out
assert "output.txt (2 Zeilen, 7 Wörter)" in out
# Only the text file remains, no VTT
assert [p.name for p in tmp_path.iterdir()] == ["output.txt"]
def test_fliesstext(fake_yt_dlp, tmp_path, monkeypatch, capsys):
long_vtt = "WEBVTT\n\n" + "".join(
f"00:00:{i:02d}.000 --> 00:00:{i + 1:02d}.000\nSatz Nummer {i} zum EU-Gipfel.\n\n"
for i in range(20)
)
monkeypatch.setattr(yt.subprocess, "run", fake_yt_dlp(GERMAN_VIDEO, vtt=long_vtt))
target = tmp_path / "rede.txt"
run_main(monkeypatch, "-u", URL, "-f", "-o", target)
lines = target.read_text(encoding="utf-8").splitlines()
assert 1 < len(lines) < 20
assert all(len(line) <= extract_text.FLOW_WIDTH for line in lines)
assert " ".join(lines) == " ".join(f"Satz Nummer {i} zum EU-Gipfel." for i in range(20))
assert "100 Wörter" in capsys.readouterr().out
def test_explicit_language_prefers_manual(fake_yt_dlp, tmp_path, monkeypatch):
run = fake_yt_dlp(GERMAN_VIDEO, vtt=VTT)
monkeypatch.setattr(yt.subprocess, "run", run)
target = tmp_path / "neu" / "rede.en.txt"
run_main(monkeypatch, "-u", URL, "-l", "en", "-o", target)
assert target.is_file()
assert "--write-subs" in run.calls[1]
def test_original_language_from_metadata_without_auto_captions(
fake_yt_dlp, tmp_path, monkeypatch
):
info = {"id": "x", "language": "fr", "subtitles": {"fr": []}, "automatic_captions": {}}
run = fake_yt_dlp(info, vtt=VTT)
monkeypatch.setattr(yt.subprocess, "run", run)
run_main(monkeypatch, "-u", URL, "-o", tmp_path / "out.txt")
assert run.calls[1][run.calls[1].index("--sub-langs") + 1] == "fr"
@pytest.mark.parametrize("info, args, message", [
# Translation only: no "en-orig", no manual "en"
(GERMAN_VIDEO, ["-l", "fr"], "Keine Untertitel in „fr“"),
({"id": "x", "subtitles": {}, "automatic_captions": {}}, [], "Originalsprache"),
])
def test_no_matching_track(fake_yt_dlp, tmp_path, monkeypatch, info, args, message):
monkeypatch.setattr(yt.subprocess, "run", fake_yt_dlp(info, vtt=VTT))
with pytest.raises(SystemExit, match=message):
run_main(monkeypatch, "-u", URL, "-o", tmp_path / "out.txt", *args)
assert not (tmp_path / "out.txt").exists()
def test_empty_subtitles(fake_yt_dlp, tmp_path, monkeypatch):
monkeypatch.setattr(yt.subprocess, "run", fake_yt_dlp(GERMAN_VIDEO, vtt="WEBVTT\n"))
with pytest.raises(SystemExit, match="keinen Text"):
run_main(monkeypatch, "-u", URL, "-o", tmp_path / "out.txt")
@pytest.mark.parametrize("args, message", [
([], "required"),
(["-u", URL, "-o", "{dir}"], "ist ein Verzeichnis"),
])
def test_cli_errors(tmp_path, monkeypatch, capsys, args, message):
args = [a.format(dir=tmp_path) for a in args]
with pytest.raises(SystemExit) as exc:
run_main(monkeypatch, *args)
assert exc.value.code == 2
assert message in capsys.readouterr().err