DeepCritical / tests /unit /tools /test_biorxiv.py
VibecoderMcSwaggins's picture
feat: Phase 11 bioRxiv Preprint Integration (#19)
e67c99f unverified
raw
history blame
6.1 kB
"""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
@pytest.fixture
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"
@pytest.mark.asyncio
@respx.mock
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()
@pytest.mark.asyncio
@respx.mock
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()
@pytest.mark.asyncio
@respx.mock
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
@pytest.mark.asyncio
@respx.mock
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 == []
@pytest.mark.asyncio
@respx.mock
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")
@pytest.mark.asyncio
@respx.mock
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)."""
@pytest.mark.integration
@pytest.mark.asyncio
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"