Spaces:
Sleeping
Sleeping
File size: 8,010 Bytes
eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 6a28f91 eadbc29 |
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 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
"""Pytest configuration and shared fixtures for court scheduling tests.
Provides common fixtures for:
- Sample cases with realistic data
- Courtrooms with various configurations
- Parameter loaders
- Temporary directories
- Pre-trained RL agents
"""
import tempfile
from datetime import date, datetime, timedelta
from pathlib import Path
from typing import List
import pytest
from src.core.case import Case, CaseStatus
from src.core.courtroom import Courtroom
from src.data.case_generator import CaseGenerator
from src.data.param_loader import ParameterLoader
# Test markers
def pytest_configure(config):
"""Configure custom pytest markers."""
config.addinivalue_line("markers", "unit: Unit tests for individual components")
config.addinivalue_line(
"markers", "integration: Integration tests for multi-component workflows"
)
config.addinivalue_line("markers", "rl: Reinforcement learning tests")
config.addinivalue_line("markers", "simulation: Simulation engine tests")
config.addinivalue_line(
"markers", "edge_case: Edge case and boundary condition tests"
)
config.addinivalue_line("markers", "failure: Failure scenario tests")
config.addinivalue_line("markers", "slow: Slow-running tests (>5 seconds)")
@pytest.fixture
def sample_cases() -> List[Case]:
"""Generate 100 realistic test cases.
Returns:
List of 100 cases with diverse types, stages, and ages
"""
generator = CaseGenerator(start=date(2024, 1, 1), end=date(2024, 3, 31), seed=42)
cases = generator.generate(100, stage_mix_auto=True)
return cases
@pytest.fixture
def small_case_set() -> List[Case]:
"""Generate 10 test cases for quick tests.
Returns:
List of 10 cases
"""
generator = CaseGenerator(start=date(2024, 1, 1), end=date(2024, 1, 10), seed=42)
cases = generator.generate(10)
return cases
@pytest.fixture
def single_case() -> Case:
"""Create a single test case.
Returns:
Single Case object in ADMISSION stage
"""
return Case(
case_id="TEST-001",
case_type="RSA",
filed_date=date(2024, 1, 1),
current_stage="ADMISSION",
last_hearing_date=None,
age_days=30,
hearing_count=0,
status=CaseStatus.PENDING,
)
@pytest.fixture
def ripe_case() -> Case:
"""Create a case that should be classified as RIPE.
Returns:
Case with sufficient hearings and proper service
"""
case = Case(
case_id="RIPE-001",
case_type="RSA",
filed_date=date(2024, 1, 1),
current_stage="ARGUMENTS",
last_hearing_date=date(2024, 2, 1),
age_days=90,
hearing_count=5,
status=CaseStatus.ACTIVE,
)
# Set additional attributes that may be needed
if hasattr(case, "service_status"):
case.service_status = "SERVED"
if hasattr(case, "compliance_status"):
case.compliance_status = "COMPLIED"
return case
@pytest.fixture
def unripe_case() -> Case:
"""Create a case that should be classified as UNRIPE.
Returns:
Case with service pending (UNRIPE_SUMMONS)
"""
case = Case(
case_id="UNRIPE-001",
case_type="CRP",
filed_date=date(2024, 1, 1),
current_stage="PRE-ADMISSION",
last_hearing_date=None,
age_days=15,
hearing_count=1,
status=CaseStatus.PENDING,
)
# Set additional attributes
if hasattr(case, "service_status"):
case.service_status = "PENDING"
if hasattr(case, "last_hearing_purpose"):
case.last_hearing_purpose = "FOR ISSUE OF SUMMONS"
return case
@pytest.fixture
def courtrooms() -> List[Courtroom]:
"""Create 5 courtrooms with realistic configurations.
Returns:
List of 5 courtrooms with varied capacities
"""
return [
Courtroom(courtroom_id=1, judge_id="J001", daily_capacity=50),
Courtroom(courtroom_id=2, judge_id="J002", daily_capacity=50),
Courtroom(courtroom_id=3, judge_id="J003", daily_capacity=45),
Courtroom(courtroom_id=4, judge_id="J004", daily_capacity=55),
Courtroom(courtroom_id=5, judge_id="J005", daily_capacity=50),
]
@pytest.fixture
def single_courtroom() -> Courtroom:
"""Create a single courtroom for simple tests.
Returns:
Single courtroom with capacity 50
"""
return Courtroom(courtroom_id=1, judge_id="J001", daily_capacity=50)
@pytest.fixture
def param_loader() -> ParameterLoader:
"""Create a parameter loader with default parameters.
Returns:
ParameterLoader instance
"""
return ParameterLoader()
@pytest.fixture
def temp_output_dir():
"""Create a temporary output directory for test artifacts.
Yields:
Path to temporary directory (cleaned up after test)
"""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)
@pytest.fixture
def test_date() -> date:
"""Standard test date for reproducibility.
Returns:
date(2024, 6, 15) - a Saturday in the middle of the year
"""
return date(2024, 6, 15)
@pytest.fixture
def test_datetime() -> datetime:
"""Standard test datetime for reproducibility.
Returns:
datetime(2024, 6, 15, 10, 0, 0)
"""
return datetime(2024, 6, 15, 10, 0, 0)
@pytest.fixture
def disposed_case() -> Case:
"""Create a case that has been disposed.
Returns:
Case in DISPOSED status
"""
case = Case(
case_id="DISPOSED-001",
case_type="CP",
filed_date=date(2024, 1, 1),
current_stage="ORDERS",
last_hearing_date=date(2024, 3, 15),
age_days=180,
hearing_count=8,
status=CaseStatus.DISPOSED,
)
return case
@pytest.fixture
def aged_case() -> Case:
"""Create an old case with many hearings.
Returns:
Case pending for 2+ years with 20+ hearings
"""
case = Case(
case_id="AGED-001",
case_type="RSA",
filed_date=date(2022, 1, 1),
current_stage="EVIDENCE",
last_hearing_date=date(2024, 5, 1),
age_days=800,
hearing_count=25,
status=CaseStatus.ACTIVE,
)
return case
@pytest.fixture
def urgent_case() -> Case:
"""Create an urgent case (filed recently, high priority).
Returns:
Case with urgency flag
"""
case = Case(
case_id="URGENT-001",
case_type="CMP",
filed_date=date(2024, 6, 1),
current_stage="ADMISSION",
last_hearing_date=None,
age_days=5,
hearing_count=0,
status=CaseStatus.PENDING,
is_urgent=True,
)
return case
# Helper functions for tests
def assert_valid_case(case: Case):
"""Assert that a case has all required fields and valid values.
Args:
case: Case to validate
"""
assert case.case_id is not None
assert case.case_type in ["RSA", "CRP", "RFA", "CA", "CCC", "CP", "MISC.CVL", "CMP"]
assert case.filed_date is not None
assert case.current_stage is not None
assert case.age_days >= 0
assert case.hearing_count >= 0
assert case.status in list(CaseStatus)
def create_case_with_hearings(n_hearings: int, days_between: int = 30) -> Case:
"""Create a case with a specific number of hearings.
Args:
n_hearings: Number of hearings to record
days_between: Days between each hearing
Returns:
Case with hearing history
"""
case = Case(
case_id=f"MULTI-HEARING-{n_hearings}",
case_type="RSA",
filed_date=date(2024, 1, 1),
current_stage="ARGUMENTS",
status=CaseStatus.ACTIVE,
)
current_date = date(2024, 1, 1)
for i in range(n_hearings):
current_date += timedelta(days=days_between)
outcome = "HEARD" if i % 3 != 0 else "ADJOURNED"
was_heard = outcome == "HEARD"
case.record_hearing(current_date, was_heard=was_heard, outcome=outcome)
return case
|