Add Stage 2.8 recall, quality gate, retries, and publish idempotency
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import json
|
||||
import unittest
|
||||
from urllib.error import HTTPError
|
||||
from unittest.mock import patch
|
||||
|
||||
from ai_daily_report.clients import BlogApiClient, OpenAICompatibleClient, fetch_text
|
||||
from ai_daily_report.clients import FetchTextError, BlogApiClient, OpenAICompatibleClient, fetch_text
|
||||
|
||||
|
||||
class FakeResponse:
|
||||
@@ -26,6 +27,28 @@ class ClientTests(unittest.TestCase):
|
||||
with patch("urllib.request.urlopen", return_value=FakeResponse("ok".encode("utf-8"))):
|
||||
self.assertEqual(fetch_text("https://example.com", 1), "ok")
|
||||
|
||||
def test_fetch_text_retries_transient_http_errors(self):
|
||||
responses = [
|
||||
HTTPError("https://example.com", 503, "Service Unavailable", {}, None),
|
||||
FakeResponse("ok".encode("utf-8")),
|
||||
]
|
||||
with patch("urllib.request.urlopen", side_effect=responses) as urlopen:
|
||||
self.assertEqual(fetch_text("https://example.com", 1, retries=1, backoff_seconds=0), "ok")
|
||||
|
||||
self.assertEqual(urlopen.call_count, 2)
|
||||
|
||||
def test_fetch_text_does_not_retry_404_and_classifies_error(self):
|
||||
with patch(
|
||||
"urllib.request.urlopen",
|
||||
side_effect=HTTPError("https://example.com", 404, "Not Found", {}, None),
|
||||
) as urlopen:
|
||||
with self.assertRaises(FetchTextError) as context:
|
||||
fetch_text("https://example.com", 1, retries=2, backoff_seconds=0)
|
||||
|
||||
self.assertEqual(urlopen.call_count, 1)
|
||||
self.assertEqual(context.exception.error_type, "http_404")
|
||||
self.assertEqual(context.exception.http_status, 404)
|
||||
|
||||
def test_openai_compatible_client_returns_message_content(self):
|
||||
body = json.dumps({"choices": [{"message": {"content": "hello"}}]}).encode("utf-8")
|
||||
with patch("urllib.request.urlopen", return_value=FakeResponse(body)):
|
||||
|
||||
Reference in New Issue
Block a user