backend/tests/test_google_translate.py
Rama master · réplica de lectura del repositorio original.
"""Tests for translation.google_translate — Google Cloud Translation v3 backend."""
from unittest.mock import MagicMock, patch
import pytest
from translation.base import TranslationResult
def _make_backend(**config_overrides):
"""Create a GoogleTranslateBackend instance without __init__ side effects."""
from translation.google_translate import GoogleTranslateBackend
backend = GoogleTranslateBackend.__new__(GoogleTranslateBackend)
backend.config = {
"project_id": "test-project",
"credentials_path": "",
"location": "global",
**config_overrides,
}
return backend
class TestGoogleBackendAttributes:
"""Tests for class-level attributes and config properties."""
def test_name_and_display_name(self):
backend = _make_backend()
assert backend.name == "google"
assert backend.display_name == "Google Cloud Translation"
def test_supports_glossary(self):
backend = _make_backend()
assert backend.supports_glossary is True
def test_supports_batch(self):
backend = _make_backend()
assert backend.supports_batch is True
assert backend.max_batch_size == 1024
def test_project_id_property(self):
backend = _make_backend(project_id="my-proj")
assert backend._project_id == "my-proj"
def test_location_default(self):
backend = _make_backend()
assert backend._location == "global"
def test_location_custom(self):
backend = _make_backend(location="us-central1")
assert backend._location == "us-central1"
def test_parent_string(self):
backend = _make_backend(project_id="proj-123", location="eu")
assert backend._parent == "projects/proj-123/locations/eu"
def test_config_fields_returned(self):
backend = _make_backend()
fields = backend.get_config_fields()
assert len(fields) == 3
keys = [f["key"] for f in fields]
assert "project_id" in keys
assert "credentials_path" in keys
assert "location" in keys
def test_get_usage_returns_empty_dict(self):
backend = _make_backend()
assert backend.get_usage() == {}
class TestCreateClient:
"""Tests for _create_client method."""
@patch("translation.google_translate._HAS_GOOGLE", False)
def test_raises_when_package_not_installed(self):
backend = _make_backend()
with pytest.raises(RuntimeError, match="google-cloud-translate package not installed"):
backend._create_client()
@patch("translation.google_translate._HAS_GOOGLE", True)
@patch("translation.google_translate.translate_v3")
def test_creates_client_successfully(self, mock_translate_v3):
backend = _make_backend()
mock_translate_v3.TranslationServiceClient.return_value = MagicMock()
client = backend._create_client()
mock_translate_v3.TranslationServiceClient.assert_called_once()
assert client is not None
@patch("translation.google_translate._HAS_GOOGLE", True)
@patch("translation.google_translate.translate_v3")
def test_sets_credentials_env_var(self, mock_translate_v3, monkeypatch):
backend = _make_backend(credentials_path="/path/to/creds.json")
mock_translate_v3.TranslationServiceClient.return_value = MagicMock()
# Clean up env after test
monkeypatch.delenv("GOOGLE_APPLICATION_CREDENTIALS", raising=False)
backend._create_client()
import os
assert os.environ.get("GOOGLE_APPLICATION_CREDENTIALS") == "/path/to/creds.json"
class TestTranslateBatch:
"""Tests for translate_batch method."""
def test_empty_lines_returns_success(self):
backend = _make_backend()
result = backend.translate_batch([], "en", "de")
assert result.success is True
assert result.translated_lines == []
@patch("translation.google_translate._HAS_GOOGLE", False)
def test_returns_failure_when_package_missing(self):
backend = _make_backend()
result = backend.translate_batch(["Hello"], "en", "de")
assert result.success is False
assert "google-cloud-translate" in result.error
@patch("translation.google_translate._HAS_GOOGLE", True)
@patch("translation.google_translate.translate_v3")
def test_successful_translation(self, mock_translate_v3):
backend = _make_backend()
mock_client = MagicMock()
mock_translate_v3.TranslationServiceClient.return_value = mock_client
mock_translation = MagicMock()
mock_translation.translated_text = "Hallo"
mock_response = MagicMock()
mock_response.translations = [mock_translation]
mock_client.translate_text.return_value = mock_response
result = backend.translate_batch(["Hello"], "en", "de")
assert result.success is True
assert result.translated_lines == ["Hallo"]
assert result.backend_name == "google"
assert result.characters_used == 5
assert result.response_time_ms >= 0
@patch("translation.google_translate._HAS_GOOGLE", True)
@patch("translation.google_translate.translate_v3")
def test_multiple_lines(self, mock_translate_v3):
backend = _make_backend()
mock_client = MagicMock()
mock_translate_v3.TranslationServiceClient.return_value = mock_client
t1, t2 = MagicMock(), MagicMock()
t1.translated_text = "Hallo"
t2.translated_text = "Welt"
mock_response = MagicMock()
mock_response.translations = [t1, t2]
mock_client.translate_text.return_value = mock_response
result = backend.translate_batch(["Hello", "World"], "en", "de")
assert result.translated_lines == ["Hallo", "Welt"]
assert result.characters_used == 10
@patch("translation.google_translate._HAS_GOOGLE", True)
@patch("translation.google_translate.translate_v3")
def test_api_error_returns_failure(self, mock_translate_v3):
backend = _make_backend()
mock_client = MagicMock()
mock_translate_v3.TranslationServiceClient.return_value = mock_client
mock_client.translate_text.side_effect = Exception("Permission denied")
result = backend.translate_batch(["Hello"], "en", "de")
assert result.success is False
assert result.translated_lines == []
assert "Permission denied" in result.error
assert result.response_time_ms >= 0
@patch("translation.google_translate._HAS_GOOGLE", True)
@patch("translation.google_translate.translate_v3")
def test_translate_request_params(self, mock_translate_v3):
backend = _make_backend(project_id="proj-x", location="europe")
mock_client = MagicMock()
mock_translate_v3.TranslationServiceClient.return_value = mock_client
mock_response = MagicMock()
mock_response.translations = [MagicMock(translated_text="Hallo")]
mock_client.translate_text.return_value = mock_response
backend.translate_batch(["Hello"], "en", "de")
call_kwargs = mock_client.translate_text.call_args[1]
request = call_kwargs["request"]
assert request["parent"] == "projects/proj-x/locations/europe"
assert request["source_language_code"] == "en"
assert request["target_language_code"] == "de"
assert request["contents"] == ["Hello"]
assert request["mime_type"] == "text/plain"
class TestHealthCheck:
"""Tests for health_check method."""
@patch("translation.google_translate._HAS_GOOGLE", False)
def test_unhealthy_when_package_missing(self):
backend = _make_backend()
healthy, msg = backend.health_check()
assert healthy is False
assert "google-cloud-translate" in msg
@patch("translation.google_translate._HAS_GOOGLE", True)
@patch("translation.google_translate.translate_v3")
def test_healthy_with_language_count(self, mock_translate_v3):
backend = _make_backend()
mock_client = MagicMock()
mock_translate_v3.TranslationServiceClient.return_value = mock_client
mock_response = MagicMock()
mock_response.languages = [MagicMock()] * 120
mock_client.get_supported_languages.return_value = mock_response
healthy, msg = backend.health_check()
assert healthy is True
assert "120 languages" in msg
@patch("translation.google_translate._HAS_GOOGLE", True)
@patch("translation.google_translate.translate_v3")
def test_unhealthy_on_credentials_error(self, mock_translate_v3):
backend = _make_backend()
mock_client = MagicMock()
mock_translate_v3.TranslationServiceClient.return_value = mock_client
class FakeCredError(Exception):
pass
FakeCredError.__name__ = "DefaultCredentialsError"
mock_client.get_supported_languages.side_effect = FakeCredError("no credentials")
healthy, msg = backend.health_check()
assert healthy is False
assert "Credentials error" in msg
@patch("translation.google_translate._HAS_GOOGLE", True)
@patch("translation.google_translate.translate_v3")
def test_unhealthy_on_generic_error(self, mock_translate_v3):
backend = _make_backend()
mock_client = MagicMock()
mock_translate_v3.TranslationServiceClient.return_value = mock_client
mock_client.get_supported_languages.side_effect = Exception("network failure")
healthy, msg = backend.health_check()
assert healthy is False
assert "Health check failed" in msg