Files
2026-07-13 13:32:05 +08:00

114 lines
3.2 KiB
Python

"""
Shared test utilities for tracing tests.
This module:
- Imports and re-exports schema validation utilities from test_integrations/utils.py
- Provides tracing-specific fixtures
- Provides helper function for creating trace_test decorator with schema paths
"""
import os
import asyncio
import pytest
# Re-export utilities from test_integrations/utils.py
from tests.test_integrations.utils import (
assert_json_object_structure,
load_trace_data,
generate_trace_json,
assert_trace_json,
)
# Configuration for generate vs assert mode
# Set to True to generate schemas, False to assert against existing schemas
# Can be overridden via environment variable: GENERATE_SCHEMAS=true pytest ...
GENERATE_MODE = os.environ.get("GENERATE_SCHEMAS", "").lower() in (
"true",
"1",
"yes",
)
_current_dir = os.path.dirname(os.path.abspath(__file__))
_schemas_dir = os.path.join(_current_dir, "schemas")
def get_schema_path(schema_name: str) -> str:
"""Get the full path to a schema file relative to the test_tracing/schemas directory."""
return os.path.join(_schemas_dir, schema_name)
def trace_test(schema_name: str):
"""
Decorator that switches between generate and assert mode based on GENERATE_MODE.
Args:
schema_name: Name of the schema file (relative path from schemas/ directory)
"""
schema_path = get_schema_path(schema_name)
if GENERATE_MODE:
return generate_trace_json(schema_path)
else:
return assert_trace_json(schema_path)
# Common fixtures
@pytest.fixture(autouse=True)
def ensure_event_loop():
"""Ensure an event loop exists for sync tests that need async operations."""
try:
loop = asyncio.get_event_loop()
if loop.is_closed():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
yield
# Don't close the loop - other tests may need it
@pytest.fixture(autouse=True)
def silence_confident_trace(monkeypatch):
"""Silence trace posting during tests."""
from deepeval.tracing.tracing import trace_manager
monkeypatch.setenv("CONFIDENT_TRACE_FLUSH", "0")
monkeypatch.setattr(
trace_manager, "post_trace", lambda *a, **k: None, raising=True
)
@pytest.fixture(autouse=True)
def reset_trace_state():
"""Reset trace manager state before and after each test."""
from deepeval.tracing.tracing import trace_manager
from deepeval.tracing.context import (
current_trace_context,
current_span_context,
)
# Reset BEFORE each test to ensure clean state
current_trace_context.set(None)
current_span_context.set(None)
trace_manager.clear_traces()
yield
# Reset AFTER each test
current_trace_context.set(None)
current_span_context.set(None)
from deepeval.tracing.types import EvalSession
trace_manager.eval_session = EvalSession()
trace_manager.clear_traces()
def get_active_trace_and_span():
"""Helper to peek at current trace/span via the observer context."""
from deepeval.tracing.context import (
current_trace_context,
current_span_context,
)
return current_trace_context.get(), current_span_context.get()