aboutsummaryrefslogtreecommitdiff
path: root/tests/test_make_faster_voices_json.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-20 17:05:21 -0400
committerhistoria <historiavg@proton.me>2026-08-20 17:05:21 -0400
commit1f2142e7f610871a6bbe6498d0709d310fcbebb1 (patch)
treedae5a4ec4187e3940aa11b433ba852226e124472 /tests/test_make_faster_voices_json.py
parent4d3530f63730b47870d25629802c0c41f0c9ffae (diff)
downloadtts-audiobook-generator-1f2142e7f610871a6bbe6498d0709d310fcbebb1.tar.gz
feat: tool scripts for server.json and voices.json
Diffstat (limited to 'tests/test_make_faster_voices_json.py')
-rw-r--r--tests/test_make_faster_voices_json.py169
1 files changed, 169 insertions, 0 deletions
diff --git a/tests/test_make_faster_voices_json.py b/tests/test_make_faster_voices_json.py
new file mode 100644
index 0000000..f26e645
--- /dev/null
+++ b/tests/test_make_faster_voices_json.py
@@ -0,0 +1,169 @@
+"""Tests for the faster-qwen3-tts voices.json generator tool."""
+
+import json
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+from unittest.mock import patch
+
+from tools import make_faster_voices_json as make_voices
+
+
+class FindWavFilesTests(unittest.TestCase):
+ def setUp(self):
+ self._tmp = tempfile.TemporaryDirectory()
+ self.folder = Path(self._tmp.name)
+
+ def tearDown(self):
+ self._tmp.cleanup()
+
+ def _touch(self, name):
+ path = self.folder / name
+ path.write_bytes(b"x")
+ return path
+
+ def test_finds_only_wavs_case_insensitive(self):
+ self._touch("b.wav")
+ self._touch("a.WAV")
+ self._touch("notes.txt")
+ (self.folder / "sub").mkdir()
+ (self.folder / "sub" / "c.wav").write_bytes(b"x")
+ names = [path.name for path in make_voices.find_wav_files(self.folder)]
+ self.assertEqual(names, ["a.WAV", "b.wav"])
+
+ def test_sorted_alphabetically_case_insensitive(self):
+ for name in ("Zed.wav", "alpha.wav", "Beta.wav"):
+ self._touch(name)
+ names = [path.name for path in make_voices.find_wav_files(self.folder)]
+ self.assertEqual(names, ["alpha.wav", "Beta.wav", "Zed.wav"])
+
+ def test_empty_directory_returns_empty_list(self):
+ self.assertEqual(make_voices.find_wav_files(self.folder), [])
+
+
+class BuildVoicesTests(unittest.TestCase):
+ def setUp(self):
+ self._tmp = tempfile.TemporaryDirectory()
+ self.folder = Path(self._tmp.name)
+ self.narrator = self.folder / "narrator.wav"
+ self.narrator.write_bytes(b"x")
+ self.other = self.folder / "other.wav"
+ self.other.write_bytes(b"x")
+
+ def tearDown(self):
+ self._tmp.cleanup()
+
+ def test_voices_named_after_basenames_with_absolute_paths(self):
+ transcripts = {str(self.narrator): "First transcript.",
+ str(self.other): "Second transcript."}
+ with patch.object(make_voices, "transcribe_reference_audio",
+ side_effect=lambda path, model_name="base": transcripts[path]):
+ voices = make_voices.build_voices([self.narrator, self.other],
+ "English", "base")
+ self.assertEqual(list(voices), ["narrator", "other"])
+ self.assertEqual(voices["narrator"]["ref_text"], "First transcript.")
+ self.assertEqual(voices["narrator"]["language"], "English")
+ self.assertTrue(Path(voices["narrator"]["ref_audio"]).is_absolute())
+ self.assertEqual(Path(voices["narrator"]["ref_audio"]), self.narrator.resolve())
+
+ def test_failed_transcription_keeps_entry_with_empty_text(self):
+ with patch.object(make_voices, "transcribe_reference_audio",
+ return_value=None):
+ voices = make_voices.build_voices([self.narrator], "English", "base")
+ self.assertEqual(voices["narrator"]["ref_text"], "")
+
+ def test_whisper_model_name_is_passed_through(self):
+ with patch.object(make_voices, "transcribe_reference_audio",
+ return_value="text") as mock_transcribe:
+ make_voices.build_voices([self.narrator], "English", "large-v3")
+ self.assertEqual(mock_transcribe.call_args.kwargs["model_name"], "large-v3")
+
+
+class MainTests(unittest.TestCase):
+ def setUp(self):
+ self._tmp = tempfile.TemporaryDirectory()
+ self.folder = Path(self._tmp.name)
+ (self.folder / "narrator.wav").write_bytes(b"x")
+ (self.folder / "alpha.wav").write_bytes(b"x")
+ self.output = self.folder / "voices.json"
+
+ def tearDown(self):
+ self._tmp.cleanup()
+
+ def _run(self, argv):
+ with patch.object(sys, "argv", ["make_voices.py"] + argv):
+ return make_voices.main()
+
+ def test_writes_json_with_alphabetical_voice_order(self):
+ with patch.object(make_voices, "transcribe_reference_audio",
+ return_value="hello"):
+ exit_code = self._run([str(self.folder)])
+ self.assertEqual(exit_code, 0)
+ data = json.loads(self.output.read_text(encoding="utf-8"))
+ self.assertEqual(list(data), ["alpha", "narrator"])
+ self.assertEqual(data["alpha"]["ref_text"], "hello")
+ self.assertEqual(data["alpha"]["language"], "English")
+
+ def test_custom_output_path(self):
+ custom = Path(self._tmp.name) / "custom.json"
+ with patch.object(make_voices, "transcribe_reference_audio",
+ return_value="hello"):
+ self._run([str(self.folder), "--output", str(custom)])
+ self.assertTrue(custom.exists())
+ self.assertFalse(self.output.exists())
+
+ def test_invalid_language_errors_before_work(self):
+ with patch.object(make_voices, "transcribe_reference_audio") as mock_transcribe:
+ with self.assertRaises(SystemExit) as ctx:
+ self._run([str(self.folder), "--language", "klingon"])
+ self.assertEqual(ctx.exception.code, 2)
+ mock_transcribe.assert_not_called()
+
+ def test_missing_input_dir_errors(self):
+ with self.assertRaises(SystemExit) as ctx:
+ self._run([str(self.folder / "nope")])
+ self.assertEqual(ctx.exception.code, 2)
+
+ def test_no_wav_files_errors(self):
+ empty = Path(tempfile.mkdtemp())
+ try:
+ with self.assertRaises(SystemExit) as ctx:
+ self._run([str(empty)])
+ self.assertEqual(ctx.exception.code, 2)
+ finally:
+ empty.rmdir()
+
+ def test_existing_output_declined_keeps_file(self):
+ self.output.write_text('{"old": true}', encoding="utf-8")
+ with patch.object(make_voices, "transcribe_reference_audio") as mock_transcribe, \
+ patch("builtins.input", return_value="n"):
+ exit_code = self._run([str(self.folder)])
+ self.assertEqual(exit_code, 1)
+ mock_transcribe.assert_not_called()
+ self.assertEqual(json.loads(self.output.read_text(encoding="utf-8")),
+ {"old": True})
+
+ def test_existing_output_accepted_overwrites(self):
+ self.output.write_text('{"old": true}', encoding="utf-8")
+ with patch.object(make_voices, "transcribe_reference_audio",
+ return_value="hello"), \
+ patch("builtins.input", return_value="y"):
+ exit_code = self._run([str(self.folder)])
+ self.assertEqual(exit_code, 0)
+ data = json.loads(self.output.read_text(encoding="utf-8"))
+ self.assertEqual(list(data), ["alpha", "narrator"])
+
+ def test_force_overwrites_without_prompt(self):
+ self.output.write_text('{"old": true}', encoding="utf-8")
+ with patch.object(make_voices, "transcribe_reference_audio",
+ return_value="hello"), \
+ patch("builtins.input", side_effect=AssertionError("prompted")):
+ exit_code = self._run([str(self.folder), "--force"])
+ self.assertEqual(exit_code, 0)
+ data = json.loads(self.output.read_text(encoding="utf-8"))
+ self.assertEqual(list(data), ["alpha", "narrator"])
+
+
+if __name__ == "__main__":
+ unittest.main()