Add Stage 2.8 recall, quality gate, retries, and publish idempotency
This commit is contained in:
78
tests/test_quality_gate.py
Normal file
78
tests/test_quality_gate.py
Normal file
@@ -0,0 +1,78 @@
|
||||
import unittest
|
||||
|
||||
from ai_daily_report.models import NewsItem, SourceResult
|
||||
from ai_daily_report.quality_gate import evaluate_quality_gate
|
||||
|
||||
|
||||
def news_item(item_id, title="Story"):
|
||||
return NewsItem(
|
||||
id=item_id,
|
||||
source_group="AI HOT",
|
||||
source_label="AI HOT",
|
||||
source_role="primary",
|
||||
source_priority=10,
|
||||
title_raw=f"{title} {item_id}",
|
||||
title_norm=f"{title} {item_id}".lower(),
|
||||
summary_raw="summary",
|
||||
url=f"https://example.com/{item_id}",
|
||||
canonical_url=f"https://example.com/{item_id}",
|
||||
)
|
||||
|
||||
|
||||
class QualityGateTests(unittest.TestCase):
|
||||
def test_warns_when_stage3_candidates_zero_for_large_item_set(self):
|
||||
items = [news_item(str(index)) for index in range(31)]
|
||||
report = evaluate_quality_gate(
|
||||
items,
|
||||
source_results=[],
|
||||
reports={"stage3": {"candidate_group_count": 0}},
|
||||
config={"warn_when_stage3_candidates_zero_min_items": 30},
|
||||
)
|
||||
|
||||
self.assertIn("stage3_candidates_zero", report["warnings"])
|
||||
self.assertEqual(report["blocking_errors"], [])
|
||||
|
||||
def test_warns_on_enabled_source_failure(self):
|
||||
report = evaluate_quality_gate(
|
||||
[news_item("a")],
|
||||
source_results=[
|
||||
SourceResult(
|
||||
source="橘鸦AI早报",
|
||||
role="supplement",
|
||||
ok=False,
|
||||
status="error",
|
||||
error="HTTPError: 404",
|
||||
)
|
||||
],
|
||||
reports={"stage3": {"candidate_group_count": 1}},
|
||||
config={"warn_on_enabled_source_failure": True},
|
||||
)
|
||||
|
||||
self.assertIn("enabled_source_failed:橘鸦AI早报:error", report["warnings"])
|
||||
self.assertEqual(report["source_failures"][0]["source"], "橘鸦AI早报")
|
||||
|
||||
def test_blocks_required_source_failure_when_configured(self):
|
||||
report = evaluate_quality_gate(
|
||||
[news_item("a")],
|
||||
source_results=[
|
||||
SourceResult(
|
||||
source="AI HOT",
|
||||
role="primary",
|
||||
ok=False,
|
||||
status="timeout",
|
||||
error="TimeoutError",
|
||||
)
|
||||
],
|
||||
reports={"stage3": {"candidate_group_count": 1}},
|
||||
config={
|
||||
"block_on_required_source_failure": True,
|
||||
"required_sources": ["AI HOT"],
|
||||
},
|
||||
)
|
||||
|
||||
self.assertIn("required_source_failed:AI HOT:timeout", report["blocking_errors"])
|
||||
self.assertTrue(report["quality_gate_failed"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user