File size: 6,417 Bytes
aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 752f5cc aa3c874 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
"""
Pytest Configuration for Roger Intelligence Platform
Provides fixtures and configuration for testing agentic AI components:
- Agent graph fixtures
- Mock LLM for unit testing
- LangSmith integration
- Golden dataset loading
"""
import os
import sys
import pytest
from pathlib import Path
from typing import Dict, Any, List
from unittest.mock import MagicMock, patch
# Add project root to path
PROJECT_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(PROJECT_ROOT))
# =============================================================================
# ENVIRONMENT CONFIGURATION
# =============================================================================
@pytest.fixture(scope="session", autouse=True)
def configure_test_environment():
"""Configure environment for testing (runs once per session)."""
# Ensure we're in test mode
os.environ["TESTING"] = "true"
# Optionally disable LangSmith tracing in unit tests for speed
# Set LANGSMITH_TRACING_TESTS=true to enable tracing in tests
if os.getenv("LANGSMITH_TRACING_TESTS", "false").lower() != "true":
os.environ["LANGCHAIN_TRACING_V2"] = "false"
yield
# Cleanup
os.environ.pop("TESTING", None)
# =============================================================================
# MOCK LLM FIXTURES
# =============================================================================
@pytest.fixture
def mock_llm():
"""
Provides a mock LLM for testing without API calls.
Returns predictable responses for deterministic testing.
"""
mock = MagicMock()
mock.invoke.return_value = MagicMock(
content='{"decision": "proceed", "reasoning": "Test response"}'
)
return mock
@pytest.fixture
def mock_groq_llm():
"""Mock GroqLLM class for testing agent nodes."""
with patch("src.llms.groqllm.GroqLLM") as mock_class:
mock_instance = MagicMock()
mock_instance.get_llm.return_value = MagicMock()
mock_class.return_value = mock_instance
yield mock_class
# =============================================================================
# AGENT FIXTURES
# =============================================================================
@pytest.fixture
def sample_agent_state() -> Dict[str, Any]:
"""Returns a sample CombinedAgentState for testing."""
return {
"run_count": 1,
"last_run_ts": "2024-01-01T00:00:00",
"domain_insights": [],
"final_ranked_feed": [],
"risk_dashboard_snapshot": {},
"route": None,
}
@pytest.fixture
def sample_domain_insight() -> Dict[str, Any]:
"""Returns a sample domain insight for testing aggregation."""
return {
"title": "Test Flood Warning",
"summary": "Heavy rainfall expected in Colombo district",
"source": "DMC",
"domain": "meteorological",
"timestamp": "2024-01-01T10:00:00",
"confidence": 0.85,
"risk_type": "Flood",
"severity": "High",
}
# =============================================================================
# GOLDEN DATASET FIXTURES
# =============================================================================
@pytest.fixture
def golden_dataset_path() -> Path:
"""Returns path to golden datasets directory."""
return PROJECT_ROOT / "tests" / "evaluation" / "golden_datasets"
@pytest.fixture
def expected_responses(golden_dataset_path) -> List[Dict]:
"""Load expected responses for LLM-as-Judge evaluation."""
import json
response_file = golden_dataset_path / "expected_responses.json"
if response_file.exists():
with open(response_file, "r", encoding="utf-8") as f:
return json.load(f)
return []
# =============================================================================
# LANGSMITH FIXTURES
# =============================================================================
@pytest.fixture
def langsmith_client():
"""
Provides LangSmith client for evaluation tests.
Returns None if not configured.
"""
try:
from src.config.langsmith_config import get_langsmith_client
return get_langsmith_client()
except ImportError:
return None
@pytest.fixture
def traced_test(langsmith_client):
"""
Context manager for traced test execution.
Automatically logs test runs to LangSmith.
"""
from contextlib import contextmanager
@contextmanager
def _traced_test(test_name: str):
if langsmith_client:
# Start a trace run
pass # LangSmith auto-traces when configured
yield
return _traced_test
# =============================================================================
# TOOL FIXTURES
# =============================================================================
@pytest.fixture
def weather_tool_response() -> str:
"""Sample response from weather tool for testing."""
import json
return json.dumps(
{
"status": "success",
"data": {
"location": "Colombo",
"temperature": 28,
"humidity": 75,
"condition": "Partly Cloudy",
"rainfall_probability": 30,
},
}
)
@pytest.fixture
def news_tool_response() -> str:
"""Sample response from news tool for testing."""
import json
return json.dumps(
{
"status": "success",
"results": [
{
"title": "Economic growth forecast for 2024",
"source": "Daily Mirror",
"url": "https://example.com/news/1",
"published": "2024-01-01",
}
],
}
)
# =============================================================================
# TEST MARKERS
# =============================================================================
def pytest_configure(config):
"""Register custom markers."""
config.addinivalue_line(
"markers", "slow: marks tests as slow (deselect with '-m \"not slow\"')"
)
config.addinivalue_line("markers", "integration: marks tests as integration tests")
config.addinivalue_line(
"markers", "evaluation: marks tests as LLM evaluation tests"
)
config.addinivalue_line(
"markers", "adversarial: marks tests as adversarial/security tests"
)
|