9cdcda5e02
- Add pytest suite (34 tests) covering scoring thresholds, dedup clustering + representative selection + time window, brief source/category diversity, avoid-term phrase matching, and text canonicalization/truncation. - Rewrite _select_diverse with an explicit, tested contract (best-first, one per source, backfill, then inject a second category by evicting the lowest-ranked pick). - classify_articles now returns attempted/succeeded/skipped (ClassifyReport) so silent model failures are visible in both the cycle and classify output. - Fix clean_text truncation to stay within max_len (ellipsis no longer overshoots). - New filters.py: canonical FilterPrefs shape (include/mute topics+flavors, avoid_terms, pauses) and pure word/phrase-boundary matching engine seeding Calm Filters. Not yet wired into the API. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
49 lines
1.6 KiB
Python
49 lines
1.6 KiB
Python
from goodnews.scoring import score_article
|
|
|
|
|
|
def test_constructive_story_is_accepted():
|
|
s = score_article("Community volunteers restore creek habitat", "A hopeful recovery effort", 3)
|
|
assert s["accepted"] == 1
|
|
assert s["constructive_score"] >= 5
|
|
assert s["reason_code"] == "heuristic_constructive_candidate"
|
|
|
|
|
|
def test_neutral_story_needs_review():
|
|
s = score_article("The weather report for tomorrow", None, 3)
|
|
assert s["accepted"] == 0
|
|
assert s["reason_code"] == "heuristic_needs_review"
|
|
|
|
|
|
def test_cortisol_heavy_is_rejected():
|
|
s = score_article("War and death as murder and attack escalate", None, 3)
|
|
assert s["accepted"] == 0
|
|
assert s["cortisol_score"] > 5
|
|
assert s["reason_code"] == "heuristic_reject_cortisol_heavy"
|
|
|
|
|
|
def test_ragebait_is_rejected_before_cortisol():
|
|
s = score_article("Senator slams rival and sparks backlash", None, 3)
|
|
assert s["accepted"] == 0
|
|
assert s["ragebait_score"] > 3
|
|
assert s["reason_code"] == "heuristic_reject_ragebait_language"
|
|
|
|
|
|
def test_pr_risk_from_source_and_terms_rejects():
|
|
s = score_article("Startup announces funding round and unveils brand", None, 6)
|
|
assert s["pr_risk_score"] > 7
|
|
assert s["accepted"] == 0
|
|
|
|
|
|
def test_all_scores_within_bounds():
|
|
s = score_article("breakthrough cure restores hope " * 10, "progress " * 20, 3)
|
|
for key in (
|
|
"constructive_score",
|
|
"cortisol_score",
|
|
"ragebait_score",
|
|
"agency_score",
|
|
"human_benefit_score",
|
|
"novelty_score",
|
|
"pr_risk_score",
|
|
):
|
|
assert 0 <= s[key] <= 10, key
|