update for mcp

This commit is contained in:
wangwei
2026-08-06 11:08:46 +08:00
parent 31bbf80aeb
commit b2feaeddb4
40 changed files with 1986 additions and 202 deletions
@@ -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()