Files
ss-tools/backend/tests/test_models_translate.py

431 lines
15 KiB
Python

# #region Test.Models.Translate [C:2] [TYPE Module] [SEMANTICS test,models,translate,sqlalchemy]
# @BRIEF Tests for models/translate.py — TranslationJob, TranslationRun, TranslationBatch,
# TranslationRecord, TranslationEvent, TranslationPreviewSession,
# TranslationPreviewRecord, TerminologyDictionary, DictionaryEntry,
# TranslationSchedule, TranslationJobDictionary, MetricSnapshot,
# TranslationLanguage, TranslationPreviewLanguage, TranslationRunLanguageStats.
# @RELATION BINDS_TO -> [TranslateModels]
# @TEST_EDGE: generate_uuid -> returns a UUID string
# @TEST_EDGE: table_names -> all model tables registered
# @TEST_EDGE: columns_exist -> key column defaults and nullable config
import pytest
from datetime import datetime, timezone
class TestGenerateUuid:
"""generate_uuid helper in translate.py."""
def test_returns_string(self):
from src.models.translate import generate_uuid
uid = generate_uuid()
assert isinstance(uid, str)
assert len(uid) > 20
def test_unique(self):
from src.models.translate import generate_uuid
uids = {generate_uuid() for _ in range(50)}
assert len(uids) == 50
class TestTranslationJob:
"""TranslationJob — main job table."""
def test_table_name(self):
from src.models.translate import TranslationJob
assert TranslationJob.__tablename__ == "translation_jobs"
def test_minimal_columns(self):
from src.models.translate import TranslationJob
obj = TranslationJob(name="Test Job", source_dialect="postgresql", target_dialect="clickhouse")
assert obj.name == "Test Job"
assert obj.source_dialect == "postgresql"
assert obj.target_dialect == "clickhouse"
# SQLAlchemy Column(default=...) only applies on INSERT via session, not at instance creation
assert obj.status is None
assert obj.batch_size is None
assert obj.disable_reasoning is None
assert obj.insert_method is None
def test_with_all_columns(self):
from src.models.translate import TranslationJob
obj = TranslationJob(
id="tj-2", name="Full Job", description="Test",
source_dialect="postgresql", target_dialect="clickhouse",
database_dialect="postgresql", status="ACTIVE",
source_datasource_id="ds-1", source_table="orders",
target_schema="public", target_table="orders_translated",
source_key_cols=["id"], target_key_cols=["id"],
translation_column="name", target_column="name_translated",
target_language_column="lang", target_source_column="source_text",
target_source_language_column="source_lang",
context_columns=["category"], target_languages=["ru", "en"],
provider_id="prov-1", batch_size=100, disable_reasoning=True,
upsert_strategy="INSERT", environment_id="env-1",
target_database_id="db-1", insert_method="direct_db",
connection_id="conn-1", created_by="admin",
)
assert obj.source_datasource_id == "ds-1"
assert obj.batch_size == 100
assert obj.disable_reasoning is True
assert obj.upsert_strategy == "INSERT"
assert obj.insert_method == "direct_db"
assert obj.connection_id == "conn-1"
def test_defaults(self):
from src.models.translate import TranslationJob
obj = TranslationJob(name="J", source_dialect="pg", target_dialect="ch")
assert obj.created_by is None
# SQLAlchemy Column(default=...) only applies on INSERT via session
assert obj.created_at is None
assert obj.updated_at is None
assert obj.target_languages is None
assert obj.provider_id is None
assert obj.description is None
assert obj.source_table is None
class TestTranslationRun:
"""TranslationRun — execution run table."""
def test_table_name(self):
from src.models.translate import TranslationRun
assert TranslationRun.__tablename__ == "translation_runs"
def test_minimal(self):
from src.models.translate import TranslationRun
obj = TranslationRun(id="tr-1", job_id="job-1", status="PENDING")
assert obj.id == "tr-1"
assert obj.job_id == "job-1"
assert obj.status == "PENDING"
def test_with_fields(self):
from src.models.translate import TranslationRun
obj = TranslationRun(
id="tr-2", job_id="job-1", status="RUNNING",
trigger_type="manual", total_records=100,
successful_records=80, failed_records=10,
skipped_records=10, cache_hits=5,
created_by="admin",
)
assert obj.trigger_type == "manual"
assert obj.total_records == 100
assert obj.cache_hits == 5
class TestTranslationBatch:
"""TranslationBatch — batch grouping table."""
def test_table_name(self):
from src.models.translate import TranslationBatch
assert TranslationBatch.__tablename__ == "translation_batches"
def test_minimal(self):
from src.models.translate import TranslationBatch
obj = TranslationBatch(id="tb-1", run_id="run-1", batch_index=0, status="PENDING")
assert obj.id == "tb-1"
assert obj.run_id == "run-1"
assert obj.batch_index == 0
assert obj.status == "PENDING"
class TestTranslationRecord:
"""TranslationRecord — individual translation result table."""
def test_table_name(self):
from src.models.translate import TranslationRecord
assert TranslationRecord.__tablename__ == "translation_records"
def test_minimal(self):
from src.models.translate import TranslationRecord
obj = TranslationRecord(id="trec-1", batch_id="b-1", run_id="run-1", status="PENDING")
assert obj.id == "trec-1"
assert obj.batch_id == "b-1"
assert obj.status == "PENDING"
def test_with_fields(self):
from src.models.translate import TranslationRecord
obj = TranslationRecord(
id="trec-2", batch_id="b-1", run_id="run-1",
source_sql="SELECT * FROM t", target_sql="SELECT * FROM t",
source_object_type="query", source_object_id="q-1",
status="SUCCESS", token_count_input=100, token_count_output=50,
)
assert obj.source_sql == "SELECT * FROM t"
assert obj.target_sql == "SELECT * FROM t"
assert obj.token_count_input == 100
def test_languages_relationship(self):
from src.models.translate import TranslationRecord
assert hasattr(TranslationRecord, "languages")
def test_table_args(self):
from src.models.translate import TranslationRecord
assert hasattr(TranslationRecord, "__table_args__")
class TestTranslationEvent:
"""TranslationEvent — audit event log."""
def test_table_name(self):
from src.models.translate import TranslationEvent
assert TranslationEvent.__tablename__ == "translation_events"
def test_minimal(self):
from src.models.translate import TranslationEvent
obj = TranslationEvent(id="te-1", job_id="j-1", event_type="JOB_CREATED")
assert obj.id == "te-1"
assert obj.job_id == "j-1"
assert obj.event_type == "JOB_CREATED"
assert obj.run_id is None
class TestTranslationPreviewSession:
"""TranslationPreviewSession — preview session."""
def test_table_name(self):
from src.models.translate import TranslationPreviewSession
assert TranslationPreviewSession.__tablename__ == "translation_preview_sessions"
def test_minimal(self):
from src.models.translate import TranslationPreviewSession
obj = TranslationPreviewSession(id="tps-1", job_id="j-1", status="ACTIVE")
assert obj.id == "tps-1"
assert obj.job_id == "j-1"
assert obj.status == "ACTIVE"
class TestTranslationPreviewRecord:
"""TranslationPreviewRecord — individual preview entry."""
def test_table_name(self):
from src.models.translate import TranslationPreviewRecord
assert TranslationPreviewRecord.__tablename__ == "translation_preview_records"
def test_minimal(self):
from src.models.translate import TranslationPreviewRecord
obj = TranslationPreviewRecord(id="tpr-1", session_id="s-1", status="PENDING")
assert obj.id == "tpr-1"
assert obj.session_id == "s-1"
assert obj.status == "PENDING"
def test_languages_relationship(self):
from src.models.translate import TranslationPreviewRecord
assert hasattr(TranslationPreviewRecord, "languages")
class TestTerminologyDictionary:
"""TerminologyDictionary — dictionary collection."""
def test_table_name(self):
from src.models.translate import TerminologyDictionary
assert TerminologyDictionary.__tablename__ == "terminology_dictionaries"
def test_minimal(self):
from src.models.translate import TerminologyDictionary
obj = TerminologyDictionary(id="td-1", name="My Dict", is_active=True)
assert obj.id == "td-1"
assert obj.name == "My Dict"
assert obj.is_active is True
class TestDictionaryEntry:
"""DictionaryEntry — individual term mapping."""
def test_table_name(self):
from src.models.translate import DictionaryEntry
assert DictionaryEntry.__tablename__ == "dictionary_entries"
def test_minimal(self):
from src.models.translate import DictionaryEntry
obj = DictionaryEntry(
id="de-1", dictionary_id="d-1",
source_term="hello", source_term_normalized="hello",
target_term="привет", source_language="en", target_language="ru",
has_context=False, is_regex=False,
)
assert obj.id == "de-1"
assert obj.source_term == "hello"
assert obj.target_term == "привет"
def test_unique_constraint(self):
from src.models.translate import DictionaryEntry
assert hasattr(DictionaryEntry, "__table_args__")
def test_with_all_fields(self):
from src.models.translate import DictionaryEntry
obj = DictionaryEntry(
id="de-2", dictionary_id="d-1",
source_term="hello", source_term_normalized="hello",
target_term="привет", source_language="en", target_language="ru",
context_notes="Greeting", context_data={"formality": "informal"},
usage_notes="Use for casual greetings", has_context=True,
is_regex=False, context_source="manual",
origin_source_language="en", origin_run_id="run-1",
)
assert obj.context_data == {"formality": "informal"}
assert obj.has_context is True
class TestTranslationSchedule:
"""TranslationSchedule — cron schedule."""
def test_table_name(self):
from src.models.translate import TranslationSchedule
assert TranslationSchedule.__tablename__ == "translation_schedules"
def test_minimal(self):
from src.models.translate import TranslationSchedule
obj = TranslationSchedule(
id="ts-1", job_id="j-1", cron_expression="0 0 * * *",
timezone="UTC", is_active=True, execution_mode="full",
)
assert obj.id == "ts-1"
assert obj.cron_expression == "0 0 * * *"
assert obj.timezone == "UTC"
assert obj.is_active is True
assert obj.execution_mode == "full"
class TestTranslationJobDictionary:
"""TranslationJobDictionary — many-to-many association."""
def test_table_name(self):
from src.models.translate import TranslationJobDictionary
assert TranslationJobDictionary.__tablename__ == "translation_job_dictionaries"
def test_minimal(self):
from src.models.translate import TranslationJobDictionary
obj = TranslationJobDictionary(id="tjd-1", job_id="j-1", dictionary_id="d-1")
assert obj.id == "tjd-1"
assert obj.job_id == "j-1"
assert obj.dictionary_id == "d-1"
class TestMetricSnapshot:
"""MetricSnapshot — translation performance metrics."""
def test_table_name(self):
from src.models.translate import MetricSnapshot
assert MetricSnapshot.__tablename__ == "translation_metric_snapshots"
def test_minimal(self):
from src.models.translate import MetricSnapshot
obj = MetricSnapshot(id="ms-1", key_hash="hash1")
assert obj.id == "ms-1"
assert obj.key_hash == "hash1"
class TestTranslationLanguage:
"""TranslationLanguage — per-language result."""
def test_table_name(self):
from src.models.translate import TranslationLanguage
assert TranslationLanguage.__tablename__ == "translation_languages"
def test_minimal(self):
from src.models.translate import TranslationLanguage
obj = TranslationLanguage(
id="tl-1", record_id="rec-1", language_code="ru",
status="pending", needs_review=False, language_overridden=False,
)
assert obj.id == "tl-1"
assert obj.language_code == "ru"
assert obj.status == "pending"
assert obj.needs_review is False
assert obj.language_overridden is False
def test_relationships(self):
from src.models.translate import TranslationLanguage
assert hasattr(TranslationLanguage, "record")
class TestTranslationPreviewLanguage:
"""TranslationPreviewLanguage — per-language preview entry."""
def test_table_name(self):
from src.models.translate import TranslationPreviewLanguage
assert TranslationPreviewLanguage.__tablename__ == "translation_preview_languages"
def test_minimal(self):
from src.models.translate import TranslationPreviewLanguage
obj = TranslationPreviewLanguage(
id="tpl-1", preview_record_id="pr-1", language_code="en",
status="pending",
)
assert obj.id == "tpl-1"
assert obj.language_code == "en"
assert obj.status == "pending"
def test_relationships(self):
from src.models.translate import TranslationPreviewLanguage
assert hasattr(TranslationPreviewLanguage, "preview_record")
class TestTranslationRunLanguageStats:
"""TranslationRunLanguageStats — per-language run stats."""
def test_table_name(self):
from src.models.translate import TranslationRunLanguageStats
assert TranslationRunLanguageStats.__tablename__ == "translation_run_language_stats"
def test_minimal(self):
from src.models.translate import TranslationRunLanguageStats
obj = TranslationRunLanguageStats(
id="trls-1", run_id="run-1", language_code="ru",
total_rows=0, translated_rows=0, token_count=0, estimated_cost=0.0,
)
assert obj.id == "trls-1"
assert obj.language_code == "ru"
assert obj.total_rows == 0
assert obj.estimated_cost == 0.0
def test_relationships(self):
from src.models.translate import TranslationRunLanguageStats
assert hasattr(TranslationRunLanguageStats, "run")
# #endregion Test.Models.Translate