Skip to content

Commit 65902a5

Browse files
committed
test: add integration tests for web search providers
1 parent e9efe00 commit 65902a5

1 file changed

Lines changed: 136 additions & 0 deletions

File tree

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import os
2+
import unittest
3+
4+
from iclaw import web_search
5+
6+
7+
class TestTavilySearchIntegration(unittest.TestCase):
8+
def setUp(self):
9+
self.api_key = os.environ.get("TAVILY_API_KEY")
10+
if not self.api_key:
11+
self.skipTest("TAVILY_API_KEY environment variable not set")
12+
13+
def test_tavily_search_returns_results(self):
14+
results = web_search.search_tavily("Python programming language", num_results=3)
15+
self.assertIsInstance(results, list)
16+
self.assertGreater(len(results), 0, "Tavily should return at least one result")
17+
for r in results:
18+
self.assertIn("title", r)
19+
self.assertIn("url", r)
20+
self.assertIn("content", r)
21+
self.assertTrue(r["url"].startswith("http"))
22+
print(f"✅ Tavily returned {len(results)} results")
23+
24+
def test_tavily_via_web_search_function(self):
25+
output = web_search.web_search(
26+
"latest news today", num_results=3, provider="tavily"
27+
)
28+
self.assertIsInstance(output, str)
29+
self.assertNotEqual(output, "No results found.")
30+
self.assertIn("### Source 1", output)
31+
self.assertIn("**Title:**", output)
32+
print(
33+
f"✅ Tavily via web_search() returned formatted output ({len(output)} chars)"
34+
)
35+
36+
def test_tavily_missing_api_key(self):
37+
original_key = os.environ.pop("TAVILY_API_KEY", None)
38+
try:
39+
results = web_search.search_tavily("test query")
40+
self.assertEqual(results, [])
41+
finally:
42+
if original_key:
43+
os.environ["TAVILY_API_KEY"] = original_key
44+
45+
46+
class TestDuckDuckGoSearchIntegration(unittest.TestCase):
47+
def test_ddg_search_returns_results(self):
48+
results = web_search.search_ddg("Python programming", num_results=5)
49+
self.assertIsInstance(results, list)
50+
self.assertGreater(len(results), 0, "DDG should return at least one result")
51+
for r in results:
52+
self.assertIn("title", r)
53+
self.assertIn("url", r)
54+
self.assertTrue(r["url"].startswith("http"))
55+
print(f"✅ DuckDuckGo returned {len(results)} results")
56+
57+
def test_ddg_via_web_search_function(self):
58+
output = web_search.web_search(
59+
"Python programming", num_results=3, provider="duckduckgo"
60+
)
61+
self.assertIsInstance(output, str)
62+
self.assertNotEqual(output, "No results found.")
63+
self.assertIn("### Source 1", output)
64+
print(
65+
f"✅ DDG via web_search() returned formatted output ({len(output)} chars)"
66+
)
67+
68+
69+
class TestBingSearchIntegration(unittest.TestCase):
70+
def test_bing_search_returns_results(self):
71+
results = web_search.search_bing("Python programming", num_results=5)
72+
self.assertIsInstance(results, list)
73+
# Bing may fail due to geo/proxy, so just check structure if results exist
74+
if results:
75+
for r in results:
76+
self.assertIn("title", r)
77+
self.assertIn("url", r)
78+
print(f"✅ Bing returned {len(results)} results")
79+
else:
80+
print("⚠️ Bing returned no results (may be blocked by proxy/geo)")
81+
82+
def test_bing_via_web_search_function(self):
83+
output = web_search.web_search(
84+
"Python programming", num_results=3, provider="bing"
85+
)
86+
self.assertIsInstance(output, str)
87+
print(f"✅ Bing via web_search() returned output ({len(output)} chars)")
88+
89+
90+
class TestStartpageSearchIntegration(unittest.TestCase):
91+
def test_startpage_search_returns_results(self):
92+
results = web_search.search_startpage("Python programming", num_results=5)
93+
self.assertIsInstance(results, list)
94+
if results:
95+
for r in results:
96+
self.assertIn("title", r)
97+
self.assertIn("url", r)
98+
print(f"✅ Startpage returned {len(results)} results")
99+
else:
100+
print("⚠️ Startpage returned no results (may be blocked by proxy/geo)")
101+
102+
103+
class TestContentExtractionIntegration(unittest.TestCase):
104+
def test_extract_text_from_wikipedia(self):
105+
text = web_search.extract_text_from_url(
106+
"https://en.wikipedia.org/wiki/Python_(programming_language)"
107+
)
108+
self.assertIsInstance(text, str)
109+
self.assertGreater(len(text), 100, "Should extract meaningful content")
110+
self.assertNotIn("Error", text)
111+
print(f"✅ Wikipedia extraction: {len(text)} chars")
112+
113+
def test_extract_text_from_github(self):
114+
text = web_search.extract_text_from_url("https://github.com/python/cpython")
115+
self.assertIsInstance(text, str)
116+
self.assertGreater(len(text), 50)
117+
print(f"✅ GitHub extraction: {len(text)} chars")
118+
119+
120+
class TestWebSearchProviderDispatch(unittest.TestCase):
121+
"""Test that web_search() correctly dispatches to different providers."""
122+
123+
def test_default_provider_is_ddg(self):
124+
output = web_search.web_search("test query", num_results=2)
125+
self.assertIsInstance(output, str)
126+
127+
def test_invalid_provider_falls_back_to_ddg(self):
128+
# Unknown provider should fall through to DDG (the else branch)
129+
output = web_search.web_search(
130+
"test query", num_results=2, provider="nonexistent"
131+
)
132+
self.assertIsInstance(output, str)
133+
134+
135+
if __name__ == "__main__":
136+
unittest.main()

0 commit comments

Comments
 (0)