update for mcp
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
"""Tests for the scheduled crawl Celery task.
|
||||
|
||||
These pin the draining contract: the task must consume every item from
|
||||
CrawlService.run_crawl(), tally per-source errors without raising on them, and
|
||||
let a genuine whole-crawl exception propagate rather than swallowing it.
|
||||
|
||||
Patches target app.shared.bootstrap.get_crawl_service — not
|
||||
perception_tasks.get_crawl_service — because the task imports it inside its
|
||||
own function body (see perception_tasks.py's docstring for why), so there is
|
||||
no module-level name in perception_tasks to intercept.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def _fake_crawl_service(events):
|
||||
"""Build a fake whose run_crawl() yields the given fixed event sequence."""
|
||||
service = MagicMock()
|
||||
service.run_crawl.return_value = iter(events)
|
||||
return service
|
||||
|
||||
|
||||
def test_task_drains_generator_and_summarizes_errors():
|
||||
"""One source error among two must not stop the run or raise."""
|
||||
events = [
|
||||
{"event": "progress", "data": {"source": "CATARC", "stage": "fetching"}},
|
||||
{"event": "error", "data": {"source": "CATARC", "message": "timeout"}},
|
||||
{"event": "progress", "data": {"source": "EUR-Lex", "stage": "fetching"}},
|
||||
{"event": "done", "data": {"total_new": 2, "total_updated": 1}},
|
||||
]
|
||||
with patch(
|
||||
"app.shared.bootstrap.get_crawl_service",
|
||||
return_value=_fake_crawl_service(events),
|
||||
):
|
||||
from app.infrastructure.tasks.perception_tasks import crawl_regulations_task
|
||||
result = crawl_regulations_task()
|
||||
|
||||
assert result == {"new": 2, "updated": 1, "source_errors": 1}
|
||||
|
||||
|
||||
def test_task_reports_zero_errors_on_a_clean_run():
|
||||
"""A run with no source errors must report source_errors: 0."""
|
||||
events = [
|
||||
{"event": "progress", "data": {"source": "CATARC", "stage": "fetching"}},
|
||||
{"event": "done", "data": {"total_new": 0, "total_updated": 0}},
|
||||
]
|
||||
with patch(
|
||||
"app.shared.bootstrap.get_crawl_service",
|
||||
return_value=_fake_crawl_service(events),
|
||||
):
|
||||
from app.infrastructure.tasks.perception_tasks import crawl_regulations_task
|
||||
result = crawl_regulations_task()
|
||||
|
||||
assert result == {"new": 0, "updated": 0, "source_errors": 0}
|
||||
|
||||
|
||||
def test_whole_crawl_exception_is_not_swallowed():
|
||||
"""A failure below run_crawl's own error handling must propagate.
|
||||
|
||||
Per-source failures are already handled inside run_crawl and never raise;
|
||||
an exception escaping the generator entirely means something unexpected
|
||||
broke, and Celery's own failure handling — not a silent catch here — is
|
||||
the intended backstop.
|
||||
"""
|
||||
broken_service = MagicMock()
|
||||
broken_service.run_crawl.side_effect = RuntimeError("event store unreachable")
|
||||
|
||||
with patch(
|
||||
"app.shared.bootstrap.get_crawl_service",
|
||||
return_value=broken_service,
|
||||
):
|
||||
from app.infrastructure.tasks.perception_tasks import crawl_regulations_task
|
||||
with pytest.raises(RuntimeError, match="event store unreachable"):
|
||||
crawl_regulations_task()
|
||||
Reference in New Issue
Block a user