test(ocr): narrow training error test to subprocess.run seam
The asyncio.to_thread patch stubbed out the entire _run_training call, hiding the real error path. Replacing it with a failing CompletedProcess from subprocess.run exercises the actual ketos-failed branch and keeps the test's intent — error counter bumps, 500 surfaces — intact. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -347,13 +347,21 @@ async def test_ocr_training_runs_total_incremented_with_recognition_success_labe
|
|||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_ocr_training_runs_total_incremented_with_recognition_error_label(fresh_metrics):
|
async def test_ocr_training_runs_total_incremented_with_recognition_error_label(fresh_metrics):
|
||||||
"""When /train's inner runner raises, the error counter bumps and the exception propagates."""
|
"""When ketos exits non-zero, the error counter bumps and the exception propagates.
|
||||||
async def fake_to_thread(func, *args, **kwargs):
|
|
||||||
raise RuntimeError("ketos train failed (exit 1): synthetic")
|
Uses the narrowest available seam — `subprocess.run` returning a failing
|
||||||
|
CompletedProcess — instead of stubbing the asyncio.to_thread boundary,
|
||||||
|
so the test exercises the real _run_training error path.
|
||||||
|
"""
|
||||||
|
from subprocess import CompletedProcess
|
||||||
|
|
||||||
|
failing_proc = CompletedProcess(
|
||||||
|
args=["ketos"], returncode=1, stdout="", stderr="synthetic ketos failure"
|
||||||
|
)
|
||||||
|
|
||||||
with patch("main.TRAINING_TOKEN", "secret-token"), \
|
with patch("main.TRAINING_TOKEN", "secret-token"), \
|
||||||
patch("main._models_ready", True), \
|
patch("main._models_ready", True), \
|
||||||
patch("main.asyncio.to_thread", side_effect=fake_to_thread):
|
patch("main.subprocess.run", return_value=failing_proc):
|
||||||
transport = ASGITransport(app=app, raise_app_exceptions=False)
|
transport = ASGITransport(app=app, raise_app_exceptions=False)
|
||||||
async with AsyncClient(transport=transport, base_url="http://test") as client:
|
async with AsyncClient(transport=transport, base_url="http://test") as client:
|
||||||
response = await client.post(
|
response = await client.post(
|
||||||
|
|||||||
Reference in New Issue
Block a user