Spaces:
Sleeping
Sleeping
File size: 5,815 Bytes
cc036ff | 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 | """
Agent service test fixtures.
Provides fixtures for agent graduation service testing.
"""
import os
import tempfile
from datetime import datetime, timedelta
from pathlib import Path
import pytest
from sqlalchemy import create_engine, exc
from sqlalchemy.orm import Session, sessionmaker
# Set TESTING environment variable BEFORE any imports
os.environ["TESTING"] = "1"
# Add parent directory to path for imports
import sys
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
from core.database import Base
from core.models import (
AgentRegistry,
AgentStatus,
Episode,
EpisodeSegment,
SupervisionSession,
SkillExecution,
)
@pytest.fixture(scope="function")
def db_session():
"""
Create a fresh in-memory database for each test.
This ensures complete isolation between test runs by using a
temporary SQLite database file that is deleted after each test.
Each test gets its own database, preventing UNIQUE constraint violations
and state leakage between tests.
"""
# Use file-based temp SQLite for tests to ensure all connections see the same database
# In-memory SQLite (:memory:) creates a separate database for each connection
fd, db_path = tempfile.mkstemp(suffix='.db')
os.close(fd) # Close the file descriptor, we just need the path
engine = create_engine(
f"sqlite:///{db_path}",
connect_args={"check_same_thread": False},
echo=False
)
# Store path for cleanup
engine._test_db_path = db_path
# Create all tables, handling missing foreign key references from optional modules
# Same approach as property_tests conftest.py
tables_created = 0
tables_skipped = 0
for table in Base.metadata.sorted_tables:
try:
table.create(engine, checkfirst=True)
tables_created += 1
except exc.NoReferencedTableError:
# Skip tables with missing FK references (from optional modules)
tables_skipped += 1
continue
except (exc.CompileError, exc.UnsupportedCompilationError):
# Skip tables with unsupported types (JSONB in SQLite)
tables_skipped += 1
continue
except Exception as e:
# Ignore duplicate table/index errors
if "already exists" in str(e).lower() or "duplicate" in str(e).lower():
continue
else:
raise
# Create session
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
session = TestingSessionLocal()
yield session
# Cleanup
session.close()
engine.dispose()
# Delete temp database file
if hasattr(engine, '_test_db_path'):
try:
os.unlink(engine._test_db_path)
except Exception:
pass # File might already be deleted
@pytest.fixture
def test_agent_student(db_session):
"""Create a test STUDENT agent."""
agent = AgentRegistry(
id="test-agent-student",
name="Test Student Agent",
category="Testing",
module_path="test.agents.student",
class_name="StudentAgent",
status=AgentStatus.STUDENT,
tenant_id="default",
created_at=datetime.now()
)
db_session.add(agent)
db_session.commit()
return agent
@pytest.fixture
def test_agent_intern(db_session):
"""Create a test INTERN agent."""
agent = AgentRegistry(
id="test-agent-intern",
name="Test Intern Agent",
category="Testing",
module_path="test.agents.intern",
class_name="InternAgent",
status=AgentStatus.INTERN,
tenant_id="default",
created_at=datetime.now()
)
db_session.add(agent)
db_session.commit()
return agent
@pytest.fixture
def test_agent_supervised(db_session):
"""Create a test SUPERVISED agent."""
agent = AgentRegistry(
id="test-agent-supervised",
name="Test Supervised Agent",
category="Testing",
module_path="test.agents.supervised",
class_name="SupervisedAgent",
status=AgentStatus.SUPERVISED,
tenant_id="default",
created_at=datetime.now()
)
db_session.add(agent)
db_session.commit()
return agent
@pytest.fixture
def test_episodes_for_intern(db_session, test_agent_intern):
"""Create test episodes for INTERN promotion."""
agent_id = test_agent_intern.id
episodes = []
for i in range(15): # More than minimum 10 for INTERN
episode = Episode(
id=f"episode-{i}",
agent_id=agent_id,
title=f"Episode {i}",
maturity_at_time="INTERN",
status="completed",
human_intervention_count=1, # Low interventions (10% rate)
constitutional_score=0.85, # Above 0.70 threshold
started_at=datetime.now() - timedelta(days=i+1)
)
db_session.add(episode)
episodes.append(episode)
db_session.commit()
return episodes
@pytest.fixture
def test_supervision_sessions(db_session, test_agent_supervised):
"""Create test supervision sessions."""
agent_id = test_agent_supervised.id
sessions = []
for i in range(5):
session = SupervisionSession(
id=f"session-{i}",
agent_id=agent_id,
agent_name="Test Supervised Agent",
supervisor_id="supervisor-123",
workspace_id="default",
status="completed",
started_at=datetime.now() - timedelta(hours=i+1),
duration_seconds=3600, # 1 hour each
intervention_count=1,
supervisor_rating=4.5
)
db_session.add(session)
sessions.append(session)
db_session.commit()
return sessions
|