Agentic-RagBot / tests /test_agents.py
MediGuard AI
feat: Initial release of MediGuard AI v2.0
c4f5f25
"""Tests for agent modules."""
import pytest
from unittest.mock import Mock, patch
from src.agents.biomarker_analyzer import BiomarkerAnalyzerAgent
from src.agents.biomarker_linker import create_biomarker_linker_agent
from src.agents.clinical_guidelines import create_clinical_guidelines_agent
from src.agents.confidence_assessor import confidence_assessor_agent
from src.agents.disease_explainer import create_disease_explainer_agent
from src.agents.response_synthesizer import response_synthesizer_agent
from src.state import GuildState
from src.config import ExplanationSOP
class TestBiomarkerAnalyzer:
"""Test BiomarkerAnalyzer agent."""
def test_analyze_normal_biomarkers(self):
"""Test analysis of normal biomarker values."""
analyzer = BiomarkerAnalyzerAgent()
state = GuildState(
patient_biomarkers={"Glucose": 90, "HbA1c": 5.0},
patient_context={},
model_prediction={"disease": "Healthy", "confidence": 0.9},
sop=ExplanationSOP(),
)
result = analyzer.analyze(state)
assert isinstance(result, dict)
assert "biomarker_flags" in result
def test_analyze_abnormal_biomarkers(self):
"""Test analysis of abnormal biomarker values."""
analyzer = BiomarkerAnalyzerAgent()
state = GuildState(
patient_biomarkers={"Glucose": 200, "HbA1c": 9.0},
patient_context={},
model_prediction={"disease": "Diabetes", "confidence": 0.9},
sop=ExplanationSOP(),
)
result = analyzer.analyze(state)
assert isinstance(result, dict)
assert "biomarker_flags" in result
class TestBiomarkerLinker:
"""Test BiomarkerLinker agent."""
def test_link_key_drivers(self):
"""Test linking biomarkers to key drivers."""
mock_retriever = Mock()
linker = create_biomarker_linker_agent(mock_retriever)
state = GuildState(
patient_biomarkers={"Glucose": 200, "HbA1c": 9.0},
patient_context={},
model_prediction={"disease": "Diabetes", "confidence": 0.9},
sop=ExplanationSOP(),
)
result = linker.link(state)
assert isinstance(result, dict)
assert "agent_outputs" in result
assert len(result["agent_outputs"]) > 0
assert "key_drivers" in result["agent_outputs"][0].findings
class TestClinicalGuidelinesAgent:
"""Test ClinicalGuidelinesAgent."""
def test_generate_recommendations(self):
"""Test generating clinical recommendations."""
mock_retriever = Mock()
mock_retriever.invoke.return_value = [] # Return empty list
agent = create_clinical_guidelines_agent(mock_retriever)
state = GuildState(
patient_biomarkers={"Glucose": 200, "HbA1c": 9.0},
patient_context={},
model_prediction={"disease": "Diabetes", "confidence": 0.9},
sop=ExplanationSOP(),
)
result = agent.recommend(state)
assert isinstance(result, dict)
assert "agent_outputs" in result
assert len(result["agent_outputs"]) > 0
findings = result["agent_outputs"][0].findings
# Check for any recommendation-related keys
assert any(key in findings for key in ["immediate_actions", "lifestyle_changes", "monitoring", "recommendations"])
class TestConfidenceAssessor:
"""Test ConfidenceAssessor agent."""
def test_assess_high_confidence(self):
"""Test confidence assessment with strong evidence."""
assessor = confidence_assessor_agent
state = GuildState(
patient_biomarkers={"Glucose": 200, "HbA1c": 9.0},
patient_context={},
model_prediction={"disease": "Diabetes", "confidence": 0.9},
retrieved_documents=[{"content": "Diabetes guidelines"}] * 5,
sop=ExplanationSOP(),
)
result = assessor.assess(state)
assert isinstance(result, dict)
# Check if result has agent_outputs or direct assessment
if "agent_outputs" in result:
findings = result["agent_outputs"][0].findings
assert "prediction_reliability" in findings
else:
# Direct assessment
assert "prediction_reliability" in result or "confidence_assessment" in result
def test_assess_low_confidence(self):
"""Test confidence assessment with weak evidence."""
assessor = confidence_assessor_agent
state = GuildState(
patient_biomarkers={"Glucose": 95, "HbA1c": 5.5},
patient_context={},
model_prediction={"disease": "Diabetes", "confidence": 0.3},
retrieved_documents=[],
sop=ExplanationSOP(),
)
result = assessor.assess(state)
assert isinstance(result, dict)
# Check if result has agent_outputs or direct assessment
if "agent_outputs" in result:
findings = result["agent_outputs"][0].findings
assert "prediction_reliability" in findings
else:
# Direct assessment
assert "prediction_reliability" in result or "confidence_assessment" in result
class TestDiseaseExplainer:
"""Test DiseaseExplainer agent."""
@patch('src.agents.disease_explainer.llm_config')
def test_explain_disease(self, mock_config):
"""Test disease explanation generation."""
mock_model = Mock()
mock_model.invoke.return_value = Mock(
content="Diabetes is a metabolic disease characterized by high blood sugar."
)
mock_config.explainer = mock_model
mock_retriever = Mock()
mock_retriever.invoke.return_value = [] # Return empty list
mock_retriever.search_kwargs = {"k": 5} # Add search_kwargs
explainer = create_disease_explainer_agent(mock_retriever)
state = GuildState(
patient_biomarkers={"Glucose": 200, "HbA1c": 9.0},
patient_context={},
model_prediction={"disease": "Diabetes", "confidence": 0.9},
sop=ExplanationSOP(),
)
result = explainer.explain(state)
assert isinstance(result, dict)
assert "agent_outputs" in result
assert len(result["agent_outputs"]) > 0
findings = result["agent_outputs"][0].findings
# Check for disease explanation related keys
assert any(key in findings for key in ["disease_explanation", "pathophysiology", "clinical_presentation", "disease"])
class TestResponseSynthesizer:
"""Test ResponseSynthesizer agent."""
@patch('src.agents.response_synthesizer.llm_config')
def test_synthesize_response(self, mock_config):
"""Test response synthesis."""
mock_model = Mock()
mock_model.invoke.return_value = Mock(
content="Based on your test results, you show signs of diabetes."
)
mock_config.synthesizer_7b = mock_model
synthesizer = response_synthesizer_agent
state = GuildState(
patient_biomarkers={"Glucose": 200, "HbA1c": 9.0},
patient_context={},
model_prediction={"disease": "Diabetes", "confidence": 0.9},
agent_outputs=[],
sop=ExplanationSOP(),
)
result = synthesizer.synthesize(state)
assert isinstance(result, dict)
# Response synthesizer returns final_response
assert "final_response" in result
final_response = result["final_response"]
# Check for conversational_summary in nested structure
if "conversational_summary" in final_response:
assert True # Found directly
elif "analysis" in final_response and "conversational_summary" in final_response["analysis"]:
assert True # Found in analysis
else:
# At least check we have some response structure
assert "analysis" in final_response or "summary" in final_response