Files
ss-tools/backend/tests/integration/test_translate_schedules.py
busya 50d6b9226e test(translate): add tests for ConnectionService, DbExecutor, orchestrator direct DB dispatch
- 9 new enhancement test files: test_connection_service.py,
  test_db_executor.py, test_orchestrator_direct_db.py, test_batch_insert.py,
  test_lang_stats.py, test_response_field_coverage.py, test_retry.py,
  test_run_service.py, test_sql_insert_service.py
- 5 new integration tests: test_superset_sqllab_e2e.py,
  test_translate_clickhouse.py, test_translate_corrections.py,
  test_translate_schedules.py, test_translate_status_fk.py
- Updated existing tests for insert_method/connection_id fields
2026-06-11 19:12:45 +03:00

236 lines
11 KiB
Python

# #region TestTranslateSchedulesIntegration [C:3] [TYPE Module] [SEMANTICS test,translate,schedule,integration]
# @BRIEF Integration tests for TranslationSchedule CRUD with real PostgreSQL via Testcontainers.
# @RELATION BINDS_TO -> [TranslationScheduler]
#
# @TEST_CONTRACT TranslationScheduler ->
# create_schedule: job_id + cron + timezone -> TranslationSchedule persisted
# get_schedule: job_id -> TranslationSchedule or ValueError
# update_schedule: job_id + fields -> updated schedule
# delete_schedule: job_id -> None (schedule removed)
# set_schedule_active: job_id + is_active -> schedule toggled
# get_next_executions: cron + tz + n -> list of ISO datetime strings
# list_active_schedules: db -> list[TranslationSchedule]
#
# @TEST_EDGE: non_existent_job -> ValueError on create
# @TEST_EDGE: get_non_existent -> ValueError with "No schedule found"
# @TEST_EDGE: delete_non_existent -> ValueError
# @TEST_EDGE: update_non_existent -> ValueError
import pytest
from sqlalchemy.orm import Session
from src.models.translate import TranslationJob, TranslationSchedule
from src.plugins.translate.scheduler import TranslationScheduler
# #region TestScheduleCRUD [C:3] [TYPE Class]
# @BRIEF Integration tests for schedule CRUD operations with real PostgreSQL.
class TestScheduleCRUD:
"""Verify TranslationScheduler CRUD with real PostgreSQL."""
def _create_job(self, db: Session, status: str = "DRAFT") -> TranslationJob:
job = TranslationJob(
name="Test Job",
status=status,
source_dialect="postgresql",
target_dialect="clickhouse",
created_by="test_user",
)
db.add(job)
db.commit()
db.refresh(job)
return job
# #region test_create_schedule [C:2] [TYPE Function]
def test_create_schedule(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
sched = scheduler.create_schedule(
job_id=job.id,
cron_expression="0 2 * * *",
timezone="Europe/Moscow",
execution_mode="new_key_only",
)
assert sched.job_id == job.id
assert sched.cron_expression == "0 2 * * *"
assert sched.timezone == "Europe/Moscow"
assert sched.execution_mode == "new_key_only"
assert sched.is_active is True
# #endregion test_create_schedule
# #region test_create_schedule_full_mode_default [C:2] [TYPE Function]
def test_create_schedule_full_mode_default(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
sched = scheduler.create_schedule(job_id=job.id, cron_expression="0 2 * * *")
assert sched.execution_mode == "full"
# #endregion test_create_schedule_full_mode_default
# #region test_get_schedule [C:2] [TYPE Function]
def test_get_schedule(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
scheduler.create_schedule(job_id=job.id, cron_expression="0 2 * * *")
db_session.commit()
result = scheduler.get_schedule(job.id)
assert result is not None
assert result.cron_expression == "0 2 * * *"
# #endregion test_get_schedule
# #region test_get_schedule_no_schedule [C:2] [TYPE Function]
def test_get_schedule_no_schedule(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
with pytest.raises(ValueError, match="No schedule found"):
scheduler.get_schedule(job.id)
# #endregion test_get_schedule_no_schedule
# #region test_update_schedule_all_fields [C:2] [TYPE Function]
def test_update_schedule_all_fields(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
scheduler.create_schedule(job_id=job.id, cron_expression="0 2 * * *")
db_session.commit()
updated = scheduler.update_schedule(
job_id=job.id, cron_expression="30 6 * * 1",
timezone_str="Asia/Tokyo", is_active=False,
execution_mode="full",
)
assert updated.cron_expression == "30 6 * * 1"
assert updated.timezone == "Asia/Tokyo"
assert updated.is_active is False
assert updated.execution_mode == "full"
# #endregion test_update_schedule_all_fields
# #region test_update_schedule_partial [C:2] [TYPE Function]
def test_update_schedule_partial(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
scheduler.create_schedule(job_id=job.id, cron_expression="0 2 * * *", timezone="Europe/Moscow")
db_session.commit()
updated = scheduler.update_schedule(job_id=job.id, cron_expression="0 4 * * *")
assert updated.cron_expression == "0 4 * * *"
assert updated.timezone == "Europe/Moscow"
# #endregion test_update_schedule_partial
# #region test_delete_schedule [C:2] [TYPE Function]
def test_delete_schedule(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
scheduler.create_schedule(job_id=job.id, cron_expression="0 2 * * *")
db_session.commit()
scheduler.delete_schedule(job.id)
with pytest.raises(ValueError, match="No schedule found"):
scheduler.get_schedule(job.id)
# #endregion test_delete_schedule
# #region test_set_schedule_active [C:2] [TYPE Function]
def test_set_schedule_active(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
scheduler.create_schedule(job_id=job.id, cron_expression="0 2 * * *", is_active=False)
db_session.commit()
sched = scheduler.set_schedule_active(job.id, True)
assert sched.is_active is True
sched = scheduler.set_schedule_active(job.id, False)
assert sched.is_active is False
# #endregion test_set_schedule_active
# #region test_set_schedule_active_twice [C:2] [TYPE Function]
def test_set_schedule_active_twice(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
scheduler.create_schedule(job_id=job.id, cron_expression="0 2 * * *")
db_session.commit()
sched = scheduler.set_schedule_active(job.id, True)
assert sched.is_active is True
sched = scheduler.set_schedule_active(job.id, True)
assert sched.is_active is True
# #endregion test_set_schedule_active_twice
# #region test_create_schedule_non_existent_job [C:2] [TYPE Function]
def test_create_schedule_non_existent_job(self, db_session: Session, mock_config_manager):
scheduler = TranslationScheduler(db_session, mock_config_manager)
with pytest.raises(ValueError, match="not found"):
scheduler.create_schedule(job_id="non-existent-id", cron_expression="0 2 * * *")
# #endregion test_create_schedule_non_existent_job
# #region test_delete_schedule_non_existent [C:2] [TYPE Function]
def test_delete_schedule_non_existent(self, db_session: Session, mock_config_manager):
scheduler = TranslationScheduler(db_session, mock_config_manager)
with pytest.raises(ValueError, match="No schedule found"):
scheduler.delete_schedule(job_id="non-existent-id")
# #endregion test_delete_schedule_non_existent
# #region test_update_schedule_no_schedule [C:2] [TYPE Function]
def test_update_schedule_no_schedule(self, db_session: Session, mock_config_manager):
job = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
with pytest.raises(ValueError, match="No schedule found"):
scheduler.update_schedule(job_id=job.id, cron_expression="0 2 * * *")
# #endregion test_update_schedule_no_schedule
# #region test_set_active_non_existent [C:2] [TYPE Function]
def test_set_active_non_existent(self, db_session: Session, mock_config_manager):
scheduler = TranslationScheduler(db_session, mock_config_manager)
with pytest.raises(ValueError, match="No schedule found"):
scheduler.set_schedule_active(job_id="non-existent", is_active=True)
# #endregion test_set_active_non_existent
# #region test_list_active_schedules [C:2] [TYPE Function]
def test_list_active_schedules(self, db_session: Session, mock_config_manager):
job1 = self._create_job(db_session)
job2 = self._create_job(db_session)
scheduler = TranslationScheduler(db_session, mock_config_manager)
scheduler.create_schedule(job_id=job1.id, cron_expression="0 2 * * *", is_active=True)
scheduler.create_schedule(job_id=job2.id, cron_expression="0 4 * * *", is_active=False)
db_session.commit()
active = TranslationScheduler.list_active_schedules(db_session)
assert len(active) == 1
assert active[0].job_id == job1.id
# #endregion test_list_active_schedules
# #region test_get_next_executions_static [C:2] [TYPE Function]
def test_get_next_executions_static(self):
executions = TranslationScheduler.get_next_executions(
cron_expression="0 2 * * *",
timezone_str="UTC",
n=3,
)
assert len(executions) == 3
for dt_str in executions:
assert "T02:00:00" in dt_str
# #endregion test_get_next_executions_static
# #region test_get_next_executions_invalid_cron [C:2] [TYPE Function]
def test_get_next_executions_invalid_cron(self):
executions = TranslationScheduler.get_next_executions(
cron_expression="invalid-cron",
timezone_str="UTC",
n=3,
)
assert executions == []
# #endregion test_get_next_executions_invalid_cron
# #region test_get_next_executions_different_timezone [C:2] [TYPE Function]
def test_get_next_executions_different_timezone(self):
executions = TranslationScheduler.get_next_executions(
cron_expression="0 2 * * *",
timezone_str="Asia/Tokyo",
n=2,
)
assert len(executions) == 2
# #endregion test_get_next_executions_different_timezone
# #endregion TestScheduleCRUD
# #endregion TestTranslateSchedulesIntegration