Files
confident-ai--deepeval/tests/test_integrations/test_crewai/test_async.py
T
2026-07-13 13:32:05 +08:00

135 lines
4.5 KiB
Python

"""
tests/test_integrations/test_crewai/test_async.py
Async CrewAI Tests
"""
import os
import pytest
from deepeval.integrations.crewai import (
instrument_crewai,
reset_crewai_instrumentation,
)
from tests.test_integrations.utils import (
assert_trace_json,
generate_trace_json,
)
from deepeval.tracing.trace_context import LlmSpanContext
from deepeval.prompt import Prompt
from deepeval.metrics import AnswerRelevancyMetric
from deepeval.tracing.tracing import trace_manager
from deepeval.tracing.otel.test_exporter import test_exporter
from deepeval.tracing.trace_test_manager import trace_testing_manager
from deepeval.tracing import trace
from deepeval.tracing.context import current_trace_context, current_span_context
# App imports
from tests.test_integrations.test_crewai.apps.evals_app import get_evals_crew
from tests.test_integrations.test_crewai.apps.simple_app import get_simple_app
from tests.test_integrations.test_crewai.apps.async_app import get_async_app
from tests.test_integrations.test_crewai.apps.tool_usage_app import (
get_tool_usage_app,
)
# =============================================================================
# CONFIGURATION
# =============================================================================
instrument_crewai()
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 trace_test(schema_name: str):
"""
Decorator that switches between generate and assert mode based on GENERATE_MODE.
"""
schema_path = os.path.join(_schemas_dir, schema_name)
if GENERATE_MODE:
return generate_trace_json(schema_path)
else:
return assert_trace_json(schema_path)
class TestCrewAIAsync:
"""Tests for asynchronous CrewAI execution."""
@pytest.mark.asyncio
@trace_test("crewai_async_kickoff.json")
async def test_async_kickoff(self):
"""Test basic async kickoff."""
crew = get_async_app()
result = await crew.kickoff_async(inputs={"input": "Async Request 1"})
assert result is not None
@pytest.mark.asyncio
@trace_test("crewai_async_tool_usage.json")
async def test_async_tool_usage(self):
"""Test async kickoff with tool usage."""
crew = get_tool_usage_app()
result = await crew.kickoff_async(inputs={"city": "Tokyo"})
assert "Weather" in str(result)
@pytest.mark.asyncio
@trace_test("crewai_kickoff_for_each_async.json")
async def test_kickoff_for_each_async(self):
"""Test async batch processing (kickoff_for_each_async)."""
crew = get_simple_app(id_suffix="_async_batch")
inputs = [{"input": "Batch 1"}, {"input": "Batch 2"}]
results = await crew.kickoff_for_each_async(inputs=inputs)
assert len(results) == 2
@pytest.mark.asyncio
@trace_test("crewai_akickoff.json")
async def test_akickoff_alias(self):
"""
Test the 'akickoff' alias (present in newer CrewAI versions).
"""
crew = get_simple_app(id_suffix="_akickoff")
# Guard clause for older CrewAI versions
if not hasattr(crew, "akickoff"):
pytest.skip("akickoff method not found on Crew object")
result = await crew.akickoff(inputs={"input": "Testing Alias"})
assert result is not None
@pytest.mark.asyncio
@trace_test("crewai_features_async.json")
async def test_features_async(self):
crew = get_evals_crew()
prompt = Prompt(alias="asd")
prompt._version = "00.00.01"
prompt.label = "test-label"
prompt.hash = "bab04ec"
with trace(
name="CrewAI Metadata Check Async",
tags=["crewai", "metadata", "async"],
user_id="user_async_002",
metadata={"env": "testing_async"},
metric_collection="trace_metrics_async_v1",
thread_id="trace_thred_id",
llm_span_context=LlmSpanContext(prompt=prompt),
metrics=[AnswerRelevancyMetric()],
):
result = await crew.kickoff_async(inputs={"input": "Async Data"})
return result
@pytest.fixture(autouse=True)
def reset_instrumentation(self):
"""Reset ALL tracing state before each test."""
reset_crewai_instrumentation()
trace_manager.clear_traces()
test_exporter.clear_span_json_list()
trace_testing_manager.test_dict = None
current_trace_context.set(None)
current_span_context.set(None)
yield