Spaces:
Running
Running
| """Unit tests for bioRxiv tool.""" | |
| import pytest | |
| import respx | |
| from httpx import Response | |
| from src.tools.biorxiv import BioRxivTool | |
| from src.utils.models import Evidence | |
| def mock_biorxiv_response(): | |
| """Mock bioRxiv API response.""" | |
| return { | |
| "collection": [ | |
| { | |
| "doi": "10.1101/2024.01.15.24301234", | |
| "title": "Metformin repurposing for Alzheimer's disease: a systematic review", | |
| "authors": "Smith, John; Jones, Alice; Brown, Bob", | |
| "date": "2024-01-15", | |
| "category": "neurology", | |
| "abstract": "Background: Metformin has shown neuroprotective effects. " | |
| "We conducted a systematic review of metformin's potential " | |
| "for Alzheimer's disease treatment.", | |
| }, | |
| { | |
| "doi": "10.1101/2024.01.10.24301111", | |
| "title": "COVID-19 vaccine efficacy study", | |
| "authors": "Wilson, C", | |
| "date": "2024-01-10", | |
| "category": "infectious diseases", | |
| "abstract": "This study evaluates COVID-19 vaccine efficacy.", | |
| }, | |
| ], | |
| "messages": [{"status": "ok", "count": 2}], | |
| } | |
| class TestBioRxivTool: | |
| """Tests for BioRxivTool.""" | |
| def test_tool_name(self): | |
| """Tool should have correct name.""" | |
| tool = BioRxivTool() | |
| assert tool.name == "biorxiv" | |
| def test_default_server_is_medrxiv(self): | |
| """Default server should be medRxiv for medical relevance.""" | |
| tool = BioRxivTool() | |
| assert tool.server == "medrxiv" | |
| async def test_search_returns_evidence(self, mock_biorxiv_response): | |
| """Search should return Evidence objects.""" | |
| respx.get(url__startswith="https://api.biorxiv.org/details").mock( | |
| return_value=Response(200, json=mock_biorxiv_response) | |
| ) | |
| tool = BioRxivTool() | |
| results = await tool.search("metformin alzheimer", max_results=5) | |
| assert len(results) == 1 # Only the matching paper | |
| assert isinstance(results[0], Evidence) | |
| assert results[0].citation.source == "biorxiv" | |
| assert "metformin" in results[0].citation.title.lower() | |
| async def test_search_filters_by_keywords(self, mock_biorxiv_response): | |
| """Search should filter papers by query keywords.""" | |
| respx.get(url__startswith="https://api.biorxiv.org/details").mock( | |
| return_value=Response(200, json=mock_biorxiv_response) | |
| ) | |
| tool = BioRxivTool() | |
| # Search for metformin - should match first paper | |
| results = await tool.search("metformin") | |
| assert len(results) == 1 | |
| assert "metformin" in results[0].citation.title.lower() | |
| # Search for COVID - should match second paper | |
| results = await tool.search("covid vaccine") | |
| assert len(results) == 1 | |
| assert "covid" in results[0].citation.title.lower() | |
| async def test_search_marks_as_preprint(self, mock_biorxiv_response): | |
| """Evidence content should note it's a preprint.""" | |
| respx.get(url__startswith="https://api.biorxiv.org/details").mock( | |
| return_value=Response(200, json=mock_biorxiv_response) | |
| ) | |
| tool = BioRxivTool() | |
| results = await tool.search("metformin") | |
| assert "PREPRINT" in results[0].content | |
| assert "Not peer-reviewed" in results[0].content | |
| async def test_search_empty_results(self): | |
| """Search should handle empty results gracefully.""" | |
| respx.get(url__startswith="https://api.biorxiv.org/details").mock( | |
| return_value=Response(200, json={"collection": [], "messages": []}) | |
| ) | |
| tool = BioRxivTool() | |
| results = await tool.search("xyznonexistent") | |
| assert results == [] | |
| async def test_search_api_error(self): | |
| """Search should raise SearchError on API failure.""" | |
| from src.utils.exceptions import SearchError | |
| respx.get(url__startswith="https://api.biorxiv.org/details").mock( | |
| return_value=Response(500, text="Internal Server Error") | |
| ) | |
| tool = BioRxivTool() | |
| with pytest.raises(SearchError): | |
| await tool.search("metformin") | |
| async def test_search_network_error(self): | |
| """Search should raise SearchError on network failure.""" | |
| import httpx | |
| from src.utils.exceptions import SearchError | |
| respx.get(url__startswith="https://api.biorxiv.org/details").mock( | |
| side_effect=httpx.RequestError("Network connection failed") | |
| ) | |
| tool = BioRxivTool() | |
| with pytest.raises(SearchError) as exc_info: | |
| await tool.search("metformin") | |
| assert "connection failed" in str(exc_info.value) | |
| def test_extract_terms(self): | |
| """Should extract meaningful search terms.""" | |
| tool = BioRxivTool() | |
| terms = tool._extract_terms("metformin for Alzheimer's disease") | |
| assert "metformin" in terms | |
| assert "alzheimer" in terms | |
| assert "disease" in terms | |
| assert "for" not in terms # Stop word | |
| assert "the" not in terms # Stop word | |
| class TestBioRxivIntegration: | |
| """Integration tests (marked for separate run).""" | |
| async def test_real_api_call(self): | |
| """Test actual API call (requires network).""" | |
| tool = BioRxivTool(days=30) # Last 30 days | |
| results = await tool.search("diabetes", max_results=3) | |
| # May or may not find results depending on recent papers | |
| # But we want to ensure the code runs without crashing | |
| assert isinstance(results, list) | |
| if results: | |
| r = results[0] | |
| assert isinstance(r, Evidence) | |
| assert r.citation.source == "biorxiv" | |