返回 last30days-skill
test_reddit_sc.py
根目录 / tests / test_reddit_sc.py
1 """Tests for reddit.py — ScrapeCreators Reddit search module."""
2
3 import unittest
4
5 # Add lib to path
6
7 from lib import reddit
8
9
10 class TestExtractCoreSubject(unittest.TestCase):
11 """Tests for _extract_core_subject()."""
12
13 def test_strips_what_are_prefix(self):
14 self.assertEqual(reddit._extract_core_subject("what are the best AI tools"), "ai tools")
15
16 def test_strips_how_to_prefix(self):
17 self.assertEqual(reddit._extract_core_subject("how to use cursor IDE"), "cursor ide")
18
19 def test_strips_noise_words(self):
20 result = reddit._extract_core_subject("latest trending updates")
21 self.assertEqual(result, "latest trending updates")
22
23 def test_preserves_product_name(self):
24 self.assertEqual(reddit._extract_core_subject("cursor IDE"), "cursor ide")
25
26 def test_strips_trailing_punctuation(self):
27 result = reddit._extract_core_subject("what is Claude?")
28 self.assertFalse(result.endswith("?"))
29
30 def test_empty_string(self):
31 result = reddit._extract_core_subject("")
32 self.assertEqual(result, "")
33
34 def test_strips_what_do_people_think(self):
35 result = reddit._extract_core_subject("what do people think about React Server Components")
36 self.assertEqual(result, "react server components")
37
38
39 class TestExpandRedditQueries(unittest.TestCase):
40 """Tests for expand_reddit_queries()."""
41
42 def test_quick_returns_one_query(self):
43 queries = reddit.expand_reddit_queries("cursor IDE", "quick")
44 self.assertGreaterEqual(len(queries), 1)
45
46 def test_default_includes_review_variant(self):
47 queries = reddit.expand_reddit_queries("cursor IDE pricing", "default")
48 self.assertTrue(any("worth it" in q or "review" in q for q in queries))
49
50 def test_default_skips_review_variant_for_prediction(self):
51 queries = reddit.expand_reddit_queries("anthropic odds", "default")
52 self.assertFalse(any("worth it" in q or "review" in q for q in queries))
53
54 def test_default_skips_review_variant_for_breaking_news(self):
55 queries = reddit.expand_reddit_queries("kanye west", "default")
56 self.assertFalse(any("worth it" in q or "review" in q for q in queries))
57
58 def test_deep_includes_issues_variant(self):
59 queries = reddit.expand_reddit_queries("cursor IDE pricing", "deep")
60 self.assertTrue(any("issues" in q or "problems" in q for q in queries))
61
62 def test_deep_skips_issues_variant_for_prediction(self):
63 queries = reddit.expand_reddit_queries("anthropic odds", "deep")
64 self.assertFalse(any("issues" in q or "problems" in q for q in queries))
65
66 def test_deep_has_more_queries_than_quick(self):
67 quick = reddit.expand_reddit_queries("cursor IDE pricing", "quick")
68 deep = reddit.expand_reddit_queries("cursor IDE pricing", "deep")
69 self.assertGreater(len(deep), len(quick))
70
71
72 class TestDiscoverSubreddits(unittest.TestCase):
73 """Tests for discover_subreddits()."""
74
75 def test_ranks_by_frequency(self):
76 results = [
77 {"subreddit": "programming", "score": 10},
78 {"subreddit": "programming", "score": 20},
79 {"subreddit": "python", "score": 5},
80 ]
81 subs = reddit.discover_subreddits(results, max_subs=5)
82 self.assertEqual(subs[0], "programming")
83
84 def test_utility_sub_penalty(self):
85 results = [
86 {"subreddit": "tipofmytongue", "score": 100},
87 {"subreddit": "tipofmytongue", "score": 100},
88 {"subreddit": "python", "score": 10},
89 ]
90 subs = reddit.discover_subreddits(results, topic="python", max_subs=5)
91 self.assertEqual(subs[0], "python")
92
93 def test_topic_name_bonus(self):
94 results = [
95 {"subreddit": "reactjs", "score": 10},
96 {"subreddit": "webdev", "score": 10},
97 ]
98 subs = reddit.discover_subreddits(results, topic="react hooks", max_subs=5)
99 self.assertEqual(subs[0], "reactjs")
100
101 def test_engagement_bonus(self):
102 results = [
103 {"subreddit": "AIsub", "ups": 500},
104 {"subreddit": "OtherSub", "ups": 5},
105 ]
106 subs = reddit.discover_subreddits(results, max_subs=5)
107 self.assertEqual(subs[0], "AIsub")
108
109 def test_max_subs_limit(self):
110 results = [{"subreddit": f"sub{i}"} for i in range(20)]
111 subs = reddit.discover_subreddits(results, max_subs=3)
112 self.assertLessEqual(len(subs), 3)
113
114 def test_empty_results(self):
115 self.assertEqual(reddit.discover_subreddits([]), [])
116
117 def test_missing_subreddit_field(self):
118 results = [{"title": "no sub field"}]
119 self.assertEqual(reddit.discover_subreddits(results), [])
120
121
122 class TestParseDate(unittest.TestCase):
123 """Tests for _parse_date()."""
124
125 def test_valid_timestamp(self):
126 self.assertEqual(reddit._parse_date(1705363200), "2024-01-16")
127
128 def test_string_timestamp(self):
129 self.assertEqual(reddit._parse_date("1705363200"), "2024-01-16")
130
131 def test_none_returns_none(self):
132 self.assertIsNone(reddit._parse_date(None))
133
134 def test_zero_returns_none(self):
135 self.assertIsNone(reddit._parse_date(0))
136
137
138 class TestDepthConfig(unittest.TestCase):
139 """Tests for DEPTH_CONFIG structure."""
140
141 def test_all_depths_exist(self):
142 for depth in ("quick", "default", "deep"):
143 self.assertIn(depth, reddit.DEPTH_CONFIG)
144
145 def test_required_keys(self):
146 required = {"global_searches", "subreddit_searches", "comment_enrichments", "timeframe"}
147 for depth, config in reddit.DEPTH_CONFIG.items():
148 self.assertTrue(required.issubset(config.keys()),
149 f"Missing keys in {depth}: {required - config.keys()}")
150
151 def test_deep_has_more_searches(self):
152 self.assertGreater(
153 reddit.DEPTH_CONFIG["deep"]["global_searches"],
154 reddit.DEPTH_CONFIG["quick"]["global_searches"],
155 )
156
157
158 class TestPostRelevance(unittest.TestCase):
159 def test_body_cannot_rescue_weak_title_too_far(self):
160 score = reddit._compute_post_relevance(
161 "anthropic odds",
162 "President Trump orders agencies to stop using Anthropic technology",
163 "Long body text eventually mentions odds and other tangential details.",
164 )
165 self.assertLess(score, 0.7)
166 self.assertGreaterEqual(score, 0.5)
167
168 def test_exact_title_match_stays_high(self):
169 score = reddit._compute_post_relevance(
170 "claude code tips",
171 "Claude Code tips for faster workflows",
172 "",
173 )
174 self.assertGreater(score, 0.7)
175
176 if __name__ == "__main__":
177 unittest.main()
178
178 lines PYTHON