testsAndMisc/linux_configuration/tests/test_transcribe_probes.py
Krzysztof kuhy Rudnicki bda24b6305
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
transcribe_helpers: split 289 -> 177 + 142
Split along the natural seam now that the file is fully covered:

  _transcribe_probes.py  177  _try_import, the four dependency probes,
                              generate_sine_wav, prepare_model, test_cuda
  transcribe_helpers.py  142  the eight _handle_* functions and main()

All 18 top-level definitions verified AST-identical to HEAD, and an AST
scan confirms neither module references a name it does not bind.

transcribe.sh is untouched - it invokes tools/transcribe_helpers.py by
path, and that path still exists with the same name and executable bit.
The CLI tests' patch targets did not move either, because main() dispatches
to names imported into its own namespace.

Verified by running every subcommand and reading the exit status directly,
since those codes are the contract transcribe.sh branches on:
python-version 0, check-faster-whisper 7, check-ctranslate2 1,
check-diarization 0, deps-installed 0; generate-wav writes the same
96044-byte WAV as before the split. 41 tests pass at 100% line and branch
on both modules; 243 pass in the directory. Over-cap files 35 -> 34.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-17 13:33:38 +02:00

126 lines
4.2 KiB
Python

"""Tests for transcribe.sh's dependency probes.
The ML dependencies (faster_whisper, torch, speechbrain, soundfile,
ctranslate2) are never installed in CI, and the module reaches them only
through ``_try_import``. Patching that one seam is what lets every probe be
tested in both directions without the real packages.
"""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING
import _transcribe_probes as helpers
import pytest
if TYPE_CHECKING:
from collections.abc import Callable
from conftest import FakeWhisper
# --------------------------------------------------------------------------- #
# The optional-dependency import seam
# --------------------------------------------------------------------------- #
def test_try_import_returns_the_module_when_present() -> None:
"""A real, importable module comes back as a module object."""
assert helpers._try_import("json") is not None
def test_try_import_returns_none_for_a_missing_module() -> None:
"""A missing optional dependency is None, not an ImportError."""
assert helpers._try_import("no_such_module_anywhere_12345") is None
# --------------------------------------------------------------------------- #
# dependency probes
# --------------------------------------------------------------------------- #
def test_get_python_version_reports_major_minor() -> None:
"""The version string is major.minor, which is what transcribe.sh parses."""
version = helpers.get_python_version()
major, _, minor = version.partition(".")
assert major.isdigit()
assert minor.isdigit()
@pytest.mark.parametrize("present", [True, False])
def test_check_faster_whisper_reports_availability(
fake_whisper: type[FakeWhisper],
importer: Callable[[dict[str, object]], object],
monkeypatch: pytest.MonkeyPatch,
*,
present: bool,
) -> None:
"""The probe is True only when faster_whisper imports."""
available = {"faster_whisper": fake_whisper()} if present else {}
monkeypatch.setattr(helpers, "_try_import", importer(available))
assert helpers.check_faster_whisper() is present
@pytest.mark.parametrize("present", [True, False])
def test_check_ctranslate2_reports_availability(
fake_whisper: type[FakeWhisper],
importer: Callable[[dict[str, object]], object],
monkeypatch: pytest.MonkeyPatch,
*,
present: bool,
) -> None:
"""The probe is True only when ctranslate2 imports."""
available = {"ctranslate2": object()} if present else {}
monkeypatch.setattr(helpers, "_try_import", importer(available))
assert helpers.check_ctranslate2() is present
def test_check_diarization_deps_needs_all_three(
fake_whisper: type[FakeWhisper],
importer: Callable[[dict[str, object]], object],
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Diarization needs soundfile, speechbrain and torch together."""
monkeypatch.setattr(
helpers,
"_try_import",
importer({"soundfile": object(), "speechbrain": object(), "torch": object()}),
)
assert helpers.check_diarization_deps() is True
@pytest.mark.parametrize("missing", ["soundfile", "speechbrain", "torch"])
def test_check_diarization_deps_warns_when_one_is_missing(
fake_whisper: type[FakeWhisper],
importer: Callable[[dict[str, object]], object],
monkeypatch: pytest.MonkeyPatch,
caplog: pytest.LogCaptureFixture,
missing: str,
) -> None:
"""Any one absent dependency downgrades to a warning, not a failure."""
available: dict[str, object] = {
name: object()
for name in ("soundfile", "speechbrain", "torch")
if name != missing
}
monkeypatch.setattr(helpers, "_try_import", importer(available))
with caplog.at_level(logging.WARNING):
result = helpers.check_diarization_deps()
assert result is False
assert "speaker labels will be skipped" in caplog.text
def test_print_deps_installed_names_the_interpreter(
fake_whisper: type[FakeWhisper],
importer: Callable[[dict[str, object]], object],
caplog: pytest.LogCaptureFixture,
) -> None:
"""The confirmation line carries the running Python version."""
with caplog.at_level(logging.INFO):
helpers.print_deps_installed()
assert "dependencies installed" in caplog.text