Files
ss-tools/backend/tests/plugins/translate/test_batch_proc_extra.py
busya 8a4310169b v4: 7643 tests passing, 83% raw / 96.9% real coverage (excl __tests__).
12 known failures — all from Agent 3 new unverified tests (mock setup issues):
- 3 dataset_review_routes_extended (DTO field mismatches)
- 1 settings_consolidated (dict key access)
- 1 llm_analysis_service_coverage (rate_limit mock)
- 1 migration_plugin (SessionLocal side_effect exhaustion)
- 1 preview (DB query vs dict key)
- 5 scheduler (datetime timezone + async mock mismatches)

NEW TEST FILES THIS SESSION:
- test_batch_insert_coverage.py — 3 tests
- test_storage_plugin.py — +3 tests
- test_search.py — +2 tests
- test_mapper.py — already 100%
- test_llm_analysis_migration_v1_to_v2.py — 14 tests
- test_llm_async_http.py — +1 test
- test_prompt_builder.py — +1 test
- test_service_datasource.py — +1 test
- test_lang_detect.py — +1 test
- test_scheduler.py — +6 tests
- test_llm_analysis_service_coverage.py — +15 tests
- test_dataset_review_routes_extended.py — +14 tests
- test_settings_consolidated.py — +13 tests

Modules pushed to 100%: _batch_insert, dictionary_entries, service_datasource,
_llm_async_http, prompt_builder, dictionary_crud, _batch_sizer, storage/plugin,
mapper.py

Session: 7194→7643 tests (+449), 80%→83% raw (+3pp), 93.4%→96.9% real (+3.5pp).
Remaining: 12 failures to fix + ~300 statements to reach 98% real coverage.
2026-06-16 09:34:10 +03:00

110 lines
4.6 KiB
Python

# #region Test.BatchProcessingService.Extra [C:3] [TYPE Module] [SEMANTICS test, batch, process, coverage]
# @BRIEF Additional coverage for BatchProcessingService edge cases.
# @RELATION BINDS_TO -> [BatchProcessingService]
# @TEST_EDGE: empty_source_text_cache -> continue on empty source_text in _check_cache
# @TEST_EDGE: provider_token_config_error -> Graceful fallback in _process_llm
# @TEST_EDGE: insert_batch_to_target_delegation -> Delegates to _batch_insert
import pytest
from unittest.mock import AsyncMock, MagicMock, patch
from src.models.translate import TranslationJob
from src.plugins.translate._batch_proc import BatchProcessingService
from .conftest import JOB_ID, RUN_ID
def _make_job(session, target_langs=None):
job = session.query(TranslationJob).filter(TranslationJob.id == JOB_ID).first()
if job is None:
job = TranslationJob(
id=JOB_ID, name="Batch Extra Test", source_dialect="en",
target_dialect=target_langs[0] if target_langs else "fr",
target_languages=target_langs or ["fr"],
status="ACTIVE", provider_id="test-provider",
)
session.add(job)
else:
if target_langs:
job.target_languages = target_langs
job.target_dialect = target_langs[0]
# Ensure provider_id is always set so _process_llm enters the try/except block
job.provider_id = "test-provider"
session.commit()
return job
def _batch_rows(count=2, detected_lang="en"):
return [
{
"row_index": str(i),
"source_text": f"Hello world {i}",
"source_data": {"table": "test", "row_id": i},
"_detected_lang": detected_lang,
}
for i in range(count)
]
class TestCheckCacheEdgeCases:
"""Cover edge cases in _check_cache."""
def test_empty_source_text_skips_cache(self, db_session):
"""When source_text is empty, continue without setting cache values."""
config = MagicMock()
svc = BatchProcessingService(db_session, config)
job = _make_job(db_session)
rows = [{"row_index": "0", "source_text": "", "_detected_lang": "en"}]
svc._check_cache(job, rows, "hash1", "hash2")
assert "_cached_lang_values" not in rows[0]
# _source_hash is NOT set because empty text hits `if not st: continue`
# (the hash is only computed when we proceed past the empty-text guard)
# So we don't assert _source_hash — it's skipped for empty text
class TestProcessLlmEdgeCases:
"""Cover edge cases in _process_llm."""
@pytest.mark.asyncio
async def test_provider_token_config_error_graceful(self, db_with_run):
"""When get_provider_token_config raises, fall through gracefully."""
session, run_id = db_with_run
config = MagicMock()
svc = BatchProcessingService(session, config)
job = _make_job(session)
rows = _batch_rows(1)
with patch('src.plugins.translate._batch_proc.LLMProviderService') as MockProv:
mock_prov_instance = MockProv.return_value
mock_prov_instance.get_provider_token_config.side_effect = ValueError("DB error")
with patch('src.plugins.translate._batch_proc.estimate_token_budget',
return_value={
"max_output_needed": 1000, "max_rows_by_output": 10,
"estimated_input_tokens": 500, "warning": None,
}):
with patch.object(svc._llm_service, 'call_llm_for_batch',
new=AsyncMock(return_value={"successful": 1, "failed": 0,
"skipped": 0, "retries": 0})):
result = await svc._process_llm(
job, run_id, rows, [], "batch-1", ["fr"],
)
assert result["successful"] == 1
class TestInsertBatchToTarget:
"""Cover insert_batch_to_target delegation."""
@pytest.mark.asyncio
async def test_delegates_to_batch_insert(self, db_with_run):
"""Ensure insert_batch_to_target delegates correctly."""
session, run_id = db_with_run
config = MagicMock()
svc = BatchProcessingService(session, config)
job = _make_job(session)
with patch('src.plugins.translate._batch_proc.insert_batch_to_target',
new=AsyncMock(return_value=None)) as mock_insert:
await svc.insert_batch_to_target(job, "batch-1", run_id)
mock_insert.assert_called_once_with(session, config, job, "batch-1", run_id)
# #endregion Test.BatchProcessingService.Extra