Initial project structure
This commit is contained in:
183
tests/conftest.py
Normal file
183
tests/conftest.py
Normal file
@@ -0,0 +1,183 @@
|
||||
"""Shared test fixtures."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
from mosaicstack_telemetry.config import TelemetryConfig
|
||||
from mosaicstack_telemetry.types.events import (
|
||||
Complexity,
|
||||
Harness,
|
||||
Outcome,
|
||||
Provider,
|
||||
TaskCompletionEvent,
|
||||
TaskType,
|
||||
)
|
||||
from mosaicstack_telemetry.types.predictions import (
|
||||
CorrectionFactors,
|
||||
PredictionData,
|
||||
PredictionMetadata,
|
||||
PredictionQuery,
|
||||
PredictionResponse,
|
||||
QualityPrediction,
|
||||
TokenDistribution,
|
||||
)
|
||||
|
||||
TEST_API_KEY = "a" * 64
|
||||
TEST_INSTANCE_ID = "12345678-1234-1234-1234-123456789abc"
|
||||
TEST_SERVER_URL = "https://telemetry.example.com"
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config() -> TelemetryConfig:
|
||||
"""Create a valid test configuration."""
|
||||
return TelemetryConfig(
|
||||
server_url=TEST_SERVER_URL,
|
||||
api_key=TEST_API_KEY,
|
||||
instance_id=TEST_INSTANCE_ID,
|
||||
submit_interval_seconds=1.0,
|
||||
max_queue_size=100,
|
||||
batch_size=10,
|
||||
request_timeout_seconds=5.0,
|
||||
max_retries=1,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def dry_run_config() -> TelemetryConfig:
|
||||
"""Create a test configuration with dry_run enabled."""
|
||||
return TelemetryConfig(
|
||||
server_url=TEST_SERVER_URL,
|
||||
api_key=TEST_API_KEY,
|
||||
instance_id=TEST_INSTANCE_ID,
|
||||
submit_interval_seconds=1.0,
|
||||
max_queue_size=100,
|
||||
batch_size=10,
|
||||
request_timeout_seconds=5.0,
|
||||
dry_run=True,
|
||||
max_retries=1,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def disabled_config() -> TelemetryConfig:
|
||||
"""Create a disabled test configuration."""
|
||||
return TelemetryConfig(
|
||||
server_url=TEST_SERVER_URL,
|
||||
api_key=TEST_API_KEY,
|
||||
instance_id=TEST_INSTANCE_ID,
|
||||
enabled=False,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def sample_instance_id() -> UUID:
|
||||
"""Return a fixed instance UUID for testing."""
|
||||
return UUID(TEST_INSTANCE_ID)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def sample_event(sample_instance_id: UUID) -> TaskCompletionEvent:
|
||||
"""Create a sample task completion event."""
|
||||
return TaskCompletionEvent(
|
||||
instance_id=sample_instance_id,
|
||||
event_id=uuid4(),
|
||||
timestamp=datetime.now(timezone.utc),
|
||||
task_duration_ms=30000,
|
||||
task_type=TaskType.IMPLEMENTATION,
|
||||
complexity=Complexity.MEDIUM,
|
||||
harness=Harness.CLAUDE_CODE,
|
||||
model="claude-sonnet-4-20250514",
|
||||
provider=Provider.ANTHROPIC,
|
||||
estimated_input_tokens=5000,
|
||||
estimated_output_tokens=2000,
|
||||
actual_input_tokens=5200,
|
||||
actual_output_tokens=1800,
|
||||
estimated_cost_usd_micros=10000,
|
||||
actual_cost_usd_micros=9500,
|
||||
quality_gate_passed=True,
|
||||
quality_gates_run=[],
|
||||
quality_gates_failed=[],
|
||||
context_compactions=0,
|
||||
context_rotations=0,
|
||||
context_utilization_final=0.4,
|
||||
outcome=Outcome.SUCCESS,
|
||||
retry_count=0,
|
||||
language="python",
|
||||
repo_size_category=None,
|
||||
)
|
||||
|
||||
|
||||
def make_event(instance_id: UUID | None = None) -> TaskCompletionEvent:
|
||||
"""Factory helper to create a sample event with optional overrides."""
|
||||
return TaskCompletionEvent(
|
||||
instance_id=instance_id or UUID(TEST_INSTANCE_ID),
|
||||
event_id=uuid4(),
|
||||
timestamp=datetime.now(timezone.utc),
|
||||
task_duration_ms=15000,
|
||||
task_type=TaskType.DEBUGGING,
|
||||
complexity=Complexity.LOW,
|
||||
harness=Harness.AIDER,
|
||||
model="gpt-4o",
|
||||
provider=Provider.OPENAI,
|
||||
estimated_input_tokens=1000,
|
||||
estimated_output_tokens=500,
|
||||
actual_input_tokens=1100,
|
||||
actual_output_tokens=480,
|
||||
estimated_cost_usd_micros=3000,
|
||||
actual_cost_usd_micros=2800,
|
||||
quality_gate_passed=True,
|
||||
quality_gates_run=[],
|
||||
quality_gates_failed=[],
|
||||
context_compactions=0,
|
||||
context_rotations=0,
|
||||
context_utilization_final=0.2,
|
||||
outcome=Outcome.SUCCESS,
|
||||
retry_count=0,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def sample_prediction_query() -> PredictionQuery:
|
||||
"""Create a sample prediction query."""
|
||||
return PredictionQuery(
|
||||
task_type=TaskType.IMPLEMENTATION,
|
||||
model="claude-sonnet-4-20250514",
|
||||
provider=Provider.ANTHROPIC,
|
||||
complexity=Complexity.MEDIUM,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def sample_prediction_response() -> PredictionResponse:
|
||||
"""Create a sample prediction response."""
|
||||
return PredictionResponse(
|
||||
prediction=PredictionData(
|
||||
input_tokens=TokenDistribution(p10=1000, p25=2000, median=3000, p75=4000, p90=5000),
|
||||
output_tokens=TokenDistribution(p10=500, p25=1000, median=1500, p75=2000, p90=2500),
|
||||
cost_usd_micros={"p10": 1000, "median": 3000, "p90": 5000},
|
||||
duration_ms={"p10": 10000, "median": 30000, "p90": 60000},
|
||||
correction_factors=CorrectionFactors(input=1.05, output=0.95),
|
||||
quality=QualityPrediction(gate_pass_rate=0.85, success_rate=0.9),
|
||||
),
|
||||
metadata=PredictionMetadata(
|
||||
sample_size=150,
|
||||
fallback_level=0,
|
||||
confidence="high",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def make_batch_response_json(events: list[TaskCompletionEvent]) -> dict:
|
||||
"""Create a batch response JSON dict for a list of events (all accepted)."""
|
||||
return {
|
||||
"accepted": len(events),
|
||||
"rejected": 0,
|
||||
"results": [
|
||||
{"event_id": str(e.event_id), "status": "accepted", "error": None}
|
||||
for e in events
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user