clarke / tests /test_ehr_agent.py
yashvshetty's picture
Clarke: NHS clinical documentation system
9636a02
Raw
History Blame
4.45 kB
"""Tests for EHRAgent parsing and deterministic context fallback behaviour."""
from __future__ import annotations
import json
from pathlib import Path
from backend.models.ehr_agent import EHRAgent, parse_agent_output
FHIR_SAMPLE_PATH = Path("data/fhir_bundles/pt-001.json")
async def _async_raw_context(patient_id: str) -> dict:
"""Return async raw context helper for monkeypatched query call.
Args:
patient_id (str): Patient identifier.
Returns:
dict: Raw grouped FHIR context payload.
"""
return _build_raw_context(patient_id)
def _build_raw_context(patient_id: str) -> dict:
"""Build deterministic raw context payload from local FHIR bundle fixture.
Args:
patient_id (str): Patient identifier used to construct context.
Returns:
dict: Aggregated resources grouped by FHIR type.
"""
bundle = json.loads(FHIR_SAMPLE_PATH.read_text(encoding="utf-8"))
grouped = {
"patient_id": patient_id,
"patients": [],
"conditions": [],
"medications": [],
"observations": [],
"allergies": [],
"diagnostic_reports": [],
"encounters": [],
}
type_mapping = {
"Patient": "patients",
"Condition": "conditions",
"MedicationRequest": "medications",
"Observation": "observations",
"AllergyIntolerance": "allergies",
"DiagnosticReport": "diagnostic_reports",
"Encounter": "encounters",
}
for entry in bundle.get("entry", []):
resource = entry.get("resource", {})
bucket = type_mapping.get(resource.get("resourceType"))
if bucket:
grouped[bucket].append(resource)
return grouped
def test_parse_agent_output_strips_system_and_markdown_fences() -> None:
"""Verify parser extracts first valid JSON object from noisy model output.
Args:
None: Uses hardcoded sample output with prompt leakage and code fences.
Returns:
None: Assertions validate parser output fields.
"""
raw = (
"<|system|>hidden instructions<|end|>\n"
"```json\n"
'{"patient_id": "pt-001", "problem_list": ["Type 2 diabetes mellitus"]}'
"\n```"
)
payload = parse_agent_output(raw)
assert payload["patient_id"] == "pt-001"
assert payload["problem_list"] == ["Type 2 diabetes mellitus"]
def test_ehr_agent_mock_mode_returns_valid_patient_context_for_pt001(monkeypatch) -> None:
"""Verify mock mode returns deterministic PatientContext populated from FHIR data.
Args:
monkeypatch (pytest.MonkeyPatch): Fixture used to patch raw context retrieval.
Returns:
None: Assertions verify key context fields for pt-001 fixtures.
"""
monkeypatch.setattr(
"backend.models.ehr_agent.get_full_patient_context",
(lambda patient_id: _async_raw_context(patient_id)),
)
agent = EHRAgent(model_id="mock")
context = agent.get_patient_context("pt-001")
assert context.patient_id == "pt-001"
assert any("diabetes" in problem.lower() for problem in context.problem_list)
assert any("metformin" in medication["name"].lower() for medication in context.medications)
assert any("penicillin" in allergy["substance"].lower() for allergy in context.allergies)
assert any(lab.name == "HbA1c" and lab.value == "55" for lab in context.recent_labs)
def test_ehr_agent_fallback_path_sets_warning_when_summarisation_fails(monkeypatch) -> None:
"""Verify retrieval warnings are added when model summarisation path fails twice.
Args:
monkeypatch (pytest.MonkeyPatch): Fixture for forcing repeated summarisation failures.
Returns:
None: Assertions verify deterministic fallback and warning propagation.
"""
monkeypatch.setattr(
"backend.models.ehr_agent.get_full_patient_context",
(lambda patient_id: _async_raw_context(patient_id)),
)
agent = EHRAgent(model_id="mock")
agent.is_mock_mode = False
monkeypatch.setattr(agent, "load_model", lambda: None)
def always_fail(_: dict) -> dict:
raise ValueError("invalid model output")
monkeypatch.setattr(agent, "_summarise_with_model", always_fail)
context = agent.get_patient_context("pt-001")
assert context.retrieval_warnings
assert "deterministic extraction" in context.retrieval_warnings[0].lower()
assert context.patient_id == "pt-001"