Spaces:
Running
Running
Commit
·
05ffeb4
1
Parent(s):
72b2667
refactor(tests): add type annotations and clean up test functions
Browse filesEnhanced test files by adding type annotations to test functions and fixtures for better clarity and type checking. Cleaned up import statements and ensured consistent formatting across test cases.
tests/unit/services/test_statistical_analyzer.py
CHANGED
|
@@ -84,7 +84,7 @@ class TestAnalysisResult:
|
|
| 84 |
"""Verdict should be one of the expected values."""
|
| 85 |
for verdict in ["SUPPORTED", "REFUTED", "INCONCLUSIVE"]:
|
| 86 |
result = AnalysisResult(
|
| 87 |
-
verdict=verdict,
|
| 88 |
confidence=0.8,
|
| 89 |
statistical_evidence="test",
|
| 90 |
code_generated="print('test')",
|
|
|
|
| 84 |
"""Verdict should be one of the expected values."""
|
| 85 |
for verdict in ["SUPPORTED", "REFUTED", "INCONCLUSIVE"]:
|
| 86 |
result = AnalysisResult(
|
| 87 |
+
verdict=verdict, # type: ignore
|
| 88 |
confidence=0.8,
|
| 89 |
statistical_evidence="test",
|
| 90 |
code_generated="print('test')",
|
tests/unit/tools/test_clinicaltrials.py
CHANGED
|
@@ -13,14 +13,14 @@ class TestClinicalTrialsTool:
|
|
| 13 |
"""Tests for ClinicalTrialsTool."""
|
| 14 |
|
| 15 |
@pytest.fixture
|
| 16 |
-
def tool(self):
|
| 17 |
return ClinicalTrialsTool()
|
| 18 |
|
| 19 |
-
def test_tool_name(self, tool):
|
| 20 |
assert tool.name == "clinicaltrials"
|
| 21 |
|
| 22 |
@pytest.mark.asyncio
|
| 23 |
-
async def test_search_uses_filters(self, tool):
|
| 24 |
"""Test that search applies status and type filters."""
|
| 25 |
mock_response = MagicMock()
|
| 26 |
mock_response.json.return_value = {"studies": []}
|
|
@@ -43,7 +43,7 @@ class TestClinicalTrialsTool:
|
|
| 43 |
assert "filter.studyType" not in params
|
| 44 |
|
| 45 |
@pytest.mark.asyncio
|
| 46 |
-
async def test_search_returns_evidence(self, tool):
|
| 47 |
"""Test that search returns Evidence objects."""
|
| 48 |
mock_study = {
|
| 49 |
"protocolSection": {
|
|
@@ -83,7 +83,7 @@ class TestClinicalTrialsTool:
|
|
| 83 |
assert "PHASE2" in results[0].content or "Phase" in results[0].content
|
| 84 |
|
| 85 |
@pytest.mark.asyncio
|
| 86 |
-
async def test_search_includes_phase_info(self, tool):
|
| 87 |
"""Test that phase information is included in content."""
|
| 88 |
mock_study = {
|
| 89 |
"protocolSection": {
|
|
@@ -117,7 +117,7 @@ class TestClinicalTrialsTool:
|
|
| 117 |
assert "PHASE3" in results[0].content or "Phase 3" in results[0].content
|
| 118 |
|
| 119 |
@pytest.mark.asyncio
|
| 120 |
-
async def test_search_empty_results(self, tool):
|
| 121 |
"""Test handling of empty results."""
|
| 122 |
mock_response = MagicMock()
|
| 123 |
mock_response.json.return_value = {"studies": []}
|
|
@@ -133,7 +133,7 @@ class TestClinicalTrialsIntegration:
|
|
| 133 |
"""Integration tests with real API."""
|
| 134 |
|
| 135 |
@pytest.mark.asyncio
|
| 136 |
-
async def test_real_api_returns_interventional(self):
|
| 137 |
"""Test that real API returns interventional studies."""
|
| 138 |
tool = ClinicalTrialsTool()
|
| 139 |
results = await tool.search("long covid treatment", max_results=3)
|
|
|
|
| 13 |
"""Tests for ClinicalTrialsTool."""
|
| 14 |
|
| 15 |
@pytest.fixture
|
| 16 |
+
def tool(self) -> ClinicalTrialsTool:
|
| 17 |
return ClinicalTrialsTool()
|
| 18 |
|
| 19 |
+
def test_tool_name(self, tool: ClinicalTrialsTool) -> None:
|
| 20 |
assert tool.name == "clinicaltrials"
|
| 21 |
|
| 22 |
@pytest.mark.asyncio
|
| 23 |
+
async def test_search_uses_filters(self, tool: ClinicalTrialsTool) -> None:
|
| 24 |
"""Test that search applies status and type filters."""
|
| 25 |
mock_response = MagicMock()
|
| 26 |
mock_response.json.return_value = {"studies": []}
|
|
|
|
| 43 |
assert "filter.studyType" not in params
|
| 44 |
|
| 45 |
@pytest.mark.asyncio
|
| 46 |
+
async def test_search_returns_evidence(self, tool: ClinicalTrialsTool) -> None:
|
| 47 |
"""Test that search returns Evidence objects."""
|
| 48 |
mock_study = {
|
| 49 |
"protocolSection": {
|
|
|
|
| 83 |
assert "PHASE2" in results[0].content or "Phase" in results[0].content
|
| 84 |
|
| 85 |
@pytest.mark.asyncio
|
| 86 |
+
async def test_search_includes_phase_info(self, tool: ClinicalTrialsTool) -> None:
|
| 87 |
"""Test that phase information is included in content."""
|
| 88 |
mock_study = {
|
| 89 |
"protocolSection": {
|
|
|
|
| 117 |
assert "PHASE3" in results[0].content or "Phase 3" in results[0].content
|
| 118 |
|
| 119 |
@pytest.mark.asyncio
|
| 120 |
+
async def test_search_empty_results(self, tool: ClinicalTrialsTool) -> None:
|
| 121 |
"""Test handling of empty results."""
|
| 122 |
mock_response = MagicMock()
|
| 123 |
mock_response.json.return_value = {"studies": []}
|
|
|
|
| 133 |
"""Integration tests with real API."""
|
| 134 |
|
| 135 |
@pytest.mark.asyncio
|
| 136 |
+
async def test_real_api_returns_interventional(self) -> None:
|
| 137 |
"""Test that real API returns interventional studies."""
|
| 138 |
tool = ClinicalTrialsTool()
|
| 139 |
results = await tool.search("long covid treatment", max_results=3)
|
tests/unit/tools/test_europepmc.py
CHANGED
|
@@ -13,14 +13,14 @@ class TestEuropePMCTool:
|
|
| 13 |
"""Tests for EuropePMCTool."""
|
| 14 |
|
| 15 |
@pytest.fixture
|
| 16 |
-
def tool(self):
|
| 17 |
return EuropePMCTool()
|
| 18 |
|
| 19 |
-
def test_tool_name(self, tool):
|
| 20 |
assert tool.name == "europepmc"
|
| 21 |
|
| 22 |
@pytest.mark.asyncio
|
| 23 |
-
async def test_search_returns_evidence(self, tool):
|
| 24 |
"""Test that search returns Evidence objects."""
|
| 25 |
mock_response = {
|
| 26 |
"resultList": {
|
|
@@ -56,7 +56,7 @@ class TestEuropePMCTool:
|
|
| 56 |
assert "Long COVID Treatment Study" in results[0].citation.title
|
| 57 |
|
| 58 |
@pytest.mark.asyncio
|
| 59 |
-
async def test_search_marks_preprints(self, tool):
|
| 60 |
"""Test that preprints are marked correctly."""
|
| 61 |
mock_response = {
|
| 62 |
"resultList": {
|
|
@@ -89,7 +89,7 @@ class TestEuropePMCTool:
|
|
| 89 |
assert results[0].citation.source == "preprint"
|
| 90 |
|
| 91 |
@pytest.mark.asyncio
|
| 92 |
-
async def test_search_empty_results(self, tool):
|
| 93 |
"""Test handling of empty results."""
|
| 94 |
mock_response = {"resultList": {"result": []}}
|
| 95 |
|
|
@@ -112,7 +112,7 @@ class TestEuropePMCIntegration:
|
|
| 112 |
"""Integration tests with real API."""
|
| 113 |
|
| 114 |
@pytest.mark.asyncio
|
| 115 |
-
async def test_real_api_call(self):
|
| 116 |
"""Test actual API returns relevant results."""
|
| 117 |
tool = EuropePMCTool()
|
| 118 |
results = await tool.search("long covid treatment", max_results=3)
|
|
|
|
| 13 |
"""Tests for EuropePMCTool."""
|
| 14 |
|
| 15 |
@pytest.fixture
|
| 16 |
+
def tool(self) -> EuropePMCTool:
|
| 17 |
return EuropePMCTool()
|
| 18 |
|
| 19 |
+
def test_tool_name(self, tool: EuropePMCTool) -> None:
|
| 20 |
assert tool.name == "europepmc"
|
| 21 |
|
| 22 |
@pytest.mark.asyncio
|
| 23 |
+
async def test_search_returns_evidence(self, tool: EuropePMCTool) -> None:
|
| 24 |
"""Test that search returns Evidence objects."""
|
| 25 |
mock_response = {
|
| 26 |
"resultList": {
|
|
|
|
| 56 |
assert "Long COVID Treatment Study" in results[0].citation.title
|
| 57 |
|
| 58 |
@pytest.mark.asyncio
|
| 59 |
+
async def test_search_marks_preprints(self, tool: EuropePMCTool) -> None:
|
| 60 |
"""Test that preprints are marked correctly."""
|
| 61 |
mock_response = {
|
| 62 |
"resultList": {
|
|
|
|
| 89 |
assert results[0].citation.source == "preprint"
|
| 90 |
|
| 91 |
@pytest.mark.asyncio
|
| 92 |
+
async def test_search_empty_results(self, tool: EuropePMCTool) -> None:
|
| 93 |
"""Test handling of empty results."""
|
| 94 |
mock_response = {"resultList": {"result": []}}
|
| 95 |
|
|
|
|
| 112 |
"""Integration tests with real API."""
|
| 113 |
|
| 114 |
@pytest.mark.asyncio
|
| 115 |
+
async def test_real_api_call(self) -> None:
|
| 116 |
"""Test actual API returns relevant results."""
|
| 117 |
tool = EuropePMCTool()
|
| 118 |
results = await tool.search("long covid treatment", max_results=3)
|
tests/unit/tools/test_query_utils.py
CHANGED
|
@@ -9,36 +9,36 @@ from src.tools.query_utils import expand_synonyms, preprocess_query, strip_quest
|
|
| 9 |
class TestQueryPreprocessing:
|
| 10 |
"""Tests for query preprocessing."""
|
| 11 |
|
| 12 |
-
def test_strip_question_words(self):
|
| 13 |
"""Test removal of question words."""
|
| 14 |
assert strip_question_words("What drugs treat cancer") == "drugs treat cancer"
|
| 15 |
assert strip_question_words("Which medications help diabetes") == "medications diabetes"
|
| 16 |
assert strip_question_words("How can we cure alzheimer") == "we cure alzheimer"
|
| 17 |
assert strip_question_words("Is metformin effective") == "metformin"
|
| 18 |
|
| 19 |
-
def test_strip_preserves_medical_terms(self):
|
| 20 |
"""Test that medical terms are preserved."""
|
| 21 |
result = strip_question_words("What is the mechanism of metformin")
|
| 22 |
assert "metformin" in result
|
| 23 |
assert "mechanism" in result
|
| 24 |
|
| 25 |
-
def test_expand_synonyms_long_covid(self):
|
| 26 |
"""Test Long COVID synonym expansion."""
|
| 27 |
result = expand_synonyms("long covid treatment")
|
| 28 |
assert "PASC" in result or "post-COVID" in result
|
| 29 |
|
| 30 |
-
def test_expand_synonyms_alzheimer(self):
|
| 31 |
"""Test Alzheimer's synonym expansion."""
|
| 32 |
result = expand_synonyms("alzheimer drug")
|
| 33 |
assert "Alzheimer" in result
|
| 34 |
|
| 35 |
-
def test_expand_synonyms_preserves_unknown(self):
|
| 36 |
"""Test that unknown terms are preserved."""
|
| 37 |
result = expand_synonyms("metformin diabetes")
|
| 38 |
assert "metformin" in result
|
| 39 |
assert "diabetes" in result
|
| 40 |
|
| 41 |
-
def test_preprocess_query_full_pipeline(self):
|
| 42 |
"""Test complete preprocessing pipeline."""
|
| 43 |
raw = "What medications show promise for Long COVID?"
|
| 44 |
result = preprocess_query(raw)
|
|
@@ -52,17 +52,17 @@ class TestQueryPreprocessing:
|
|
| 52 |
assert "PASC" in result or "post-COVID" in result or "long covid" in result.lower()
|
| 53 |
assert "medications" in result.lower() or "drug" in result.lower()
|
| 54 |
|
| 55 |
-
def test_preprocess_query_removes_punctuation(self):
|
| 56 |
"""Test that question marks are removed."""
|
| 57 |
result = preprocess_query("Is metformin safe?")
|
| 58 |
assert "?" not in result
|
| 59 |
|
| 60 |
-
def test_preprocess_query_handles_empty(self):
|
| 61 |
"""Test handling of empty/whitespace queries."""
|
| 62 |
assert preprocess_query("") == ""
|
| 63 |
assert preprocess_query(" ") == ""
|
| 64 |
|
| 65 |
-
def test_preprocess_query_already_clean(self):
|
| 66 |
"""Test that clean queries pass through."""
|
| 67 |
clean = "metformin diabetes mechanism"
|
| 68 |
result = preprocess_query(clean)
|
|
|
|
| 9 |
class TestQueryPreprocessing:
|
| 10 |
"""Tests for query preprocessing."""
|
| 11 |
|
| 12 |
+
def test_strip_question_words(self) -> None:
|
| 13 |
"""Test removal of question words."""
|
| 14 |
assert strip_question_words("What drugs treat cancer") == "drugs treat cancer"
|
| 15 |
assert strip_question_words("Which medications help diabetes") == "medications diabetes"
|
| 16 |
assert strip_question_words("How can we cure alzheimer") == "we cure alzheimer"
|
| 17 |
assert strip_question_words("Is metformin effective") == "metformin"
|
| 18 |
|
| 19 |
+
def test_strip_preserves_medical_terms(self) -> None:
|
| 20 |
"""Test that medical terms are preserved."""
|
| 21 |
result = strip_question_words("What is the mechanism of metformin")
|
| 22 |
assert "metformin" in result
|
| 23 |
assert "mechanism" in result
|
| 24 |
|
| 25 |
+
def test_expand_synonyms_long_covid(self) -> None:
|
| 26 |
"""Test Long COVID synonym expansion."""
|
| 27 |
result = expand_synonyms("long covid treatment")
|
| 28 |
assert "PASC" in result or "post-COVID" in result
|
| 29 |
|
| 30 |
+
def test_expand_synonyms_alzheimer(self) -> None:
|
| 31 |
"""Test Alzheimer's synonym expansion."""
|
| 32 |
result = expand_synonyms("alzheimer drug")
|
| 33 |
assert "Alzheimer" in result
|
| 34 |
|
| 35 |
+
def test_expand_synonyms_preserves_unknown(self) -> None:
|
| 36 |
"""Test that unknown terms are preserved."""
|
| 37 |
result = expand_synonyms("metformin diabetes")
|
| 38 |
assert "metformin" in result
|
| 39 |
assert "diabetes" in result
|
| 40 |
|
| 41 |
+
def test_preprocess_query_full_pipeline(self) -> None:
|
| 42 |
"""Test complete preprocessing pipeline."""
|
| 43 |
raw = "What medications show promise for Long COVID?"
|
| 44 |
result = preprocess_query(raw)
|
|
|
|
| 52 |
assert "PASC" in result or "post-COVID" in result or "long covid" in result.lower()
|
| 53 |
assert "medications" in result.lower() or "drug" in result.lower()
|
| 54 |
|
| 55 |
+
def test_preprocess_query_removes_punctuation(self) -> None:
|
| 56 |
"""Test that question marks are removed."""
|
| 57 |
result = preprocess_query("Is metformin safe?")
|
| 58 |
assert "?" not in result
|
| 59 |
|
| 60 |
+
def test_preprocess_query_handles_empty(self) -> None:
|
| 61 |
"""Test handling of empty/whitespace queries."""
|
| 62 |
assert preprocess_query("") == ""
|
| 63 |
assert preprocess_query(" ") == ""
|
| 64 |
|
| 65 |
+
def test_preprocess_query_already_clean(self) -> None:
|
| 66 |
"""Test that clean queries pass through."""
|
| 67 |
clean = "metformin diabetes mechanism"
|
| 68 |
result = preprocess_query(clean)
|
tests/unit/utils/test_config.py
CHANGED
|
@@ -40,7 +40,7 @@ class TestSettings:
|
|
| 40 |
def test_get_api_key_openai_missing_raises(self):
|
| 41 |
"""get_api_key should raise ConfigurationError when OpenAI key is not set."""
|
| 42 |
with patch.dict(os.environ, {"LLM_PROVIDER": "openai"}, clear=True):
|
| 43 |
-
settings = Settings(
|
| 44 |
with pytest.raises(ConfigurationError, match="OPENAI_API_KEY not set"):
|
| 45 |
settings.get_api_key()
|
| 46 |
|
|
@@ -55,6 +55,6 @@ class TestSettings:
|
|
| 55 |
def test_get_api_key_anthropic_missing_raises(self):
|
| 56 |
"""get_api_key should raise ConfigurationError when Anthropic key is not set."""
|
| 57 |
with patch.dict(os.environ, {"LLM_PROVIDER": "anthropic"}, clear=True):
|
| 58 |
-
settings = Settings(
|
| 59 |
with pytest.raises(ConfigurationError, match="ANTHROPIC_API_KEY not set"):
|
| 60 |
settings.get_api_key()
|
|
|
|
| 40 |
def test_get_api_key_openai_missing_raises(self):
|
| 41 |
"""get_api_key should raise ConfigurationError when OpenAI key is not set."""
|
| 42 |
with patch.dict(os.environ, {"LLM_PROVIDER": "openai"}, clear=True):
|
| 43 |
+
settings = Settings()
|
| 44 |
with pytest.raises(ConfigurationError, match="OPENAI_API_KEY not set"):
|
| 45 |
settings.get_api_key()
|
| 46 |
|
|
|
|
| 55 |
def test_get_api_key_anthropic_missing_raises(self):
|
| 56 |
"""get_api_key should raise ConfigurationError when Anthropic key is not set."""
|
| 57 |
with patch.dict(os.environ, {"LLM_PROVIDER": "anthropic"}, clear=True):
|
| 58 |
+
settings = Settings()
|
| 59 |
with pytest.raises(ConfigurationError, match="ANTHROPIC_API_KEY not set"):
|
| 60 |
settings.get_api_key()
|