diff options
Diffstat (limited to 'app/tests/test_backends_envs.py')
| -rw-r--r-- | app/tests/test_backends_envs.py | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/app/tests/test_backends_envs.py b/app/tests/test_backends_envs.py index 184a3b3..8b17458 100644 --- a/app/tests/test_backends_envs.py +++ b/app/tests/test_backends_envs.py @@ -16,25 +16,47 @@ class EnvPathTests(unittest.TestCase): self.assertEqual(envs.ENV_DIR.name, "tts") self.assertEqual(envs.ENV_DIR.parent.name, "envs") + def test_backend_env_dirs_are_separate_from_the_app_env(self): + # Each pip-installed backend gets its own venv next to the app's: + # qwen-tts and faster-qwen3-tts both ship a qwen_tts module with + # conflicting transformers pins, so they must never share one. + self.assertEqual(envs.QWEN_ENV_DIR.name, "qwen") + self.assertEqual(envs.FASTER_ENV_DIR.name, "faster") + self.assertEqual(envs.QWEN_ENV_DIR.parent, envs.ENV_DIR.parent) + distinct = {envs.ENV_DIR, envs.QWEN_ENV_DIR, envs.FASTER_ENV_DIR} + self.assertEqual(len(distinct), 3) + def test_env_python_posix(self): with patch.object(envs, "_is_windows", return_value=False): self.assertEqual(envs.env_python(), envs.ENV_DIR / "bin" / "python") + self.assertEqual( + envs.env_python(envs.QWEN_ENV_DIR), + envs.QWEN_ENV_DIR / "bin" / "python") def test_env_python_windows(self): with patch.object(envs, "_is_windows", return_value=True): self.assertEqual(envs.env_python(), envs.ENV_DIR / "Scripts" / "python.exe") + self.assertEqual( + envs.env_python(envs.FASTER_ENV_DIR), + envs.FASTER_ENV_DIR / "Scripts" / "python.exe") def test_env_script_posix(self): with patch.object(envs, "_is_windows", return_value=False): self.assertEqual(envs.env_script("qwen-tts-demo"), envs.ENV_DIR / "bin" / "qwen-tts-demo") + self.assertEqual( + envs.env_script("qwen-tts-demo", envs.QWEN_ENV_DIR), + envs.QWEN_ENV_DIR / "bin" / "qwen-tts-demo") def test_env_script_windows(self): with patch.object(envs, "_is_windows", return_value=True): self.assertEqual(envs.env_script("qwen-tts-demo"), envs.ENV_DIR / "Scripts" / "qwen-tts-demo.exe") + self.assertEqual( + envs.env_script("qwen-tts-demo", envs.QWEN_ENV_DIR), + envs.QWEN_ENV_DIR / "Scripts" / "qwen-tts-demo.exe") def test_env_exists_false_when_python_missing(self): with patch.object(envs, "env_python", @@ -63,6 +85,13 @@ class CreateEnvTests(unittest.TestCase): self.assertEqual(argv[2], "venv") self.assertEqual(argv[3], str(envs.ENV_DIR)) + def test_create_env_targets_the_requested_env_dir(self): + with patch.object(envs.common, "run_console_subprocess", + return_value=0) as run: + envs.create_env(envs.FASTER_ENV_DIR) + argv = run.call_args[0][0] + self.assertEqual(argv[3], str(envs.FASTER_ENV_DIR)) + def test_create_env_reports_remediation_on_failure(self): with patch.object(envs.common, "run_console_subprocess", return_value=1): @@ -84,12 +113,31 @@ class PipInstallTests(unittest.TestCase): side_effect=fake_run): rc = envs.pip_install(["qwen-tts"]) self.assertEqual(rc, 0) - mk.assert_called_once_with() + mk.assert_called_once_with(None) # The actual pip call targets the venv's python. self.assertEqual(calls[0][0], str(envs.env_python())) self.assertIn("pip", calls[0]) self.assertIn("qwen-tts", calls[0]) + def test_backend_env_targets_the_backend_python_and_env(self): + calls = [] + + def fake_run(argv, **kwargs): + calls.append(list(argv)) + return 0 + + with patch.object(envs, "env_exists", return_value=False), \ + patch.object(envs, "create_env", return_value=0) as mk, \ + patch.object(envs.common, "run_console_subprocess", + side_effect=fake_run): + rc = envs.pip_install(["qwen-tts"], env_dir=envs.QWEN_ENV_DIR) + self.assertEqual(rc, 0) + # Both create-if-missing and pip itself are scoped to the qwen env; + # the app env is never touched. + mk.assert_called_once_with(envs.QWEN_ENV_DIR) + self.assertEqual(calls[0][0], + str(envs.env_python(envs.QWEN_ENV_DIR))) + def test_skips_create_when_env_exists(self): with patch.object(envs, "env_exists", return_value=True), \ patch.object(envs, "create_env") as mk, \ @@ -115,6 +163,13 @@ class PipUninstallTests(unittest.TestCase): self.assertEqual(rc, 0) run.assert_not_called() + def test_missing_backend_env_is_also_a_noop(self): + with patch.object(envs, "env_exists", return_value=False), \ + patch.object(envs.common, "run_console_subprocess") as run: + rc = envs.pip_uninstall(["qwen-tts"], env_dir=envs.QWEN_ENV_DIR) + self.assertEqual(rc, 0) + run.assert_not_called() + def test_runs_pip_uninstall_against_the_venv_python(self): calls = [] @@ -133,6 +188,21 @@ class PipUninstallTests(unittest.TestCase): self.assertIn("-y", calls[0]) self.assertIn("qwen-tts", calls[0]) + def test_targets_the_requested_env_python(self): + calls = [] + + def fake_run(argv, **kwargs): + calls.append(list(argv)) + return 0 + + with patch.object(envs, "env_exists", return_value=True), \ + patch.object(envs.common, "run_console_subprocess", + side_effect=fake_run): + envs.pip_uninstall(["faster-qwen3-tts"], + env_dir=envs.FASTER_ENV_DIR) + self.assertEqual(calls[0][0], + str(envs.env_python(envs.FASTER_ENV_DIR))) + def test_streams_to_emit_when_given(self): with patch.object(envs, "env_exists", return_value=True), \ patch.object(envs.common, "run_console_subprocess", @@ -167,6 +237,18 @@ class ModuleAvailableTests(unittest.TestCase): self.assertEqual(argv[0], str(envs.env_python())) self.assertIn("import qwen_tts", argv[2]) + def test_probes_the_requested_env_interpreter(self): + import subprocess + fake = subprocess.CompletedProcess(args=["x"], returncode=0) + with patch.object(envs, "env_exists", return_value=True), \ + patch("subprocess.run", return_value=fake) as run: + self.assertTrue( + envs.module_available("qwen_tts", envs.QWEN_ENV_DIR)) + argv = run.call_args[0][0] + self.assertEqual(argv[0], + str(envs.env_python(envs.QWEN_ENV_DIR))) + self.assertIn("import qwen_tts", argv[2]) + def test_false_when_subprocess_exits_nonzero(self): import subprocess fake = subprocess.CompletedProcess(args=["x"], returncode=1) |
