|
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- import unittest
-
- from structs.headline import Headline
- from structs.story import Story
- from services.stories import cluster_stories
-
-
- def h(text, tokens, url=""):
- return Headline(text, tokens, url)
-
-
- class TestHeadlineSourceTracking(unittest.TestCase):
- def test_domain_extraction_strips_www_and_lowercases(self):
- headline = h("A story", ["a"], "https://www.CNN.com/us")
- self.assertEqual(headline.domain, "cnn.com")
-
- def test_domain_extraction_section_paths_collapse(self):
- us = h("A story", ["a"], "https://www.cnn.com/us")
- politics = h("A story", ["a"], "https://cnn.com/politics")
- self.assertEqual(us.domain, politics.domain)
-
- def test_domain_is_none_when_source_missing(self):
- self.assertIsNone(h("A story", ["a"]).domain)
- self.assertIsNone(h("A story", ["a"], "").domain)
- self.assertIsNone(h("A story", ["a"], " ").domain)
-
-
- class TestStory(unittest.TestCase):
- def test_sources_dedup_preserving_order(self):
- story = Story([
- h("Story A", ["a"], "https://www.cnn.com/us"),
- h("Story A", ["a"], "https://foxnews.com/politics"),
- h("Story A", ["a"], "https://www.cnn.com/politics"),
- ])
- self.assertEqual(story.sources, ["cnn.com", "foxnews.com"])
- self.assertEqual(story.source_count, 2)
-
- def test_representative_is_longest_headline(self):
- story = Story([
- h("Short", ["short"], "https://a.com"),
- h("A much longer descriptive headline", ["long"], "https://b.com"),
- ])
- self.assertEqual(story.representative, "A much longer descriptive headline")
-
-
- class TestClusterStories(unittest.TestCase):
- def test_transitive_clustering_merges_chain(self):
- # Three headlines sharing tokens pairwise but not as a triple.
- headlines = [
- h("alpha beta", ["alpha", "beta"], "https://a.com"),
- h("beta gamma", ["beta", "gamma"], "https://b.com"),
- h("delta epsilon", ["delta", "epsilon"], "https://c.com"),
- ]
- stories = cluster_stories(headlines, threshold=0.4)
- texts = {s.representative for s in stories}
- # alpha/beta and beta/gamma share "beta" -> one cluster; delta/epsilon separate.
- self.assertEqual(len(stories), 2)
- self.assertIn("alpha beta", texts)
- self.assertIn("delta epsilon", texts)
-
- def test_non_similar_headlines_stay_separate(self):
- headlines = [
- h("apple pie", ["apple", "pie"], "https://a.com"),
- h("quantum physics", ["quantum", "physics"], "https://b.com"),
- ]
- stories = cluster_stories(headlines, threshold=0.6)
- self.assertEqual(len(stories), 2)
-
- def test_empty_input(self):
- self.assertEqual(cluster_stories([], 0.75), [])
-
-
- if __name__ == "__main__":
- unittest.main()
|