forked from cleveragents/cleveragents-core
165 lines
5.2 KiB
Python
165 lines
5.2 KiB
Python
"""
|
|
BDD test environment setup for reactive CleverAgents.
|
|
"""
|
|
|
|
import asyncio
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
# Increase recursion limit to handle deep import chains in langchain/torch/transformers
|
|
sys.setrecursionlimit(5000)
|
|
|
|
|
|
def before_all(context):
|
|
"""Set up test environment before all tests."""
|
|
context.temp_dir = Path(tempfile.mkdtemp())
|
|
|
|
# Set dummy API keys for testing
|
|
os.environ["OPENAI_API_KEY"] = "test-key-openai"
|
|
os.environ["ANTHROPIC_API_KEY"] = "test-key-anthropic"
|
|
os.environ["GOOGLE_GEMINI_API_KEY"] = "test-key-google"
|
|
|
|
# Create async event loop for tests
|
|
context.loop = asyncio.new_event_loop()
|
|
asyncio.set_event_loop(context.loop)
|
|
|
|
|
|
def after_all(context):
|
|
"""Clean up test environment after all tests."""
|
|
# Clean up temp directory
|
|
import shutil
|
|
|
|
shutil.rmtree(context.temp_dir, ignore_errors=True)
|
|
|
|
# Close async event loop with proper cleanup
|
|
if hasattr(context, "loop"):
|
|
# Cancel all remaining tasks
|
|
try:
|
|
pending = asyncio.all_tasks(context.loop)
|
|
for task in pending:
|
|
task.cancel()
|
|
except Exception:
|
|
pass
|
|
|
|
# Close the loop without waiting for tasks
|
|
try:
|
|
context.loop.close()
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def before_scenario(context, scenario):
|
|
"""Set up before each scenario."""
|
|
context.config_files = []
|
|
context.app = None
|
|
context.result = None
|
|
context.error = None
|
|
context.unsafe = False
|
|
|
|
# Create scenario-specific temp directory
|
|
context.scenario_temp = context.temp_dir / f"scenario_{scenario.name.replace(' ', '_')}"
|
|
context.scenario_temp.mkdir(exist_ok=True)
|
|
|
|
# Set up test context for InlineYAMLJinja tests - not needed for simplified tests
|
|
# if "InlineYAMLJinja" in scenario.feature.name or "inline_yaml_jinja" in str(scenario.feature.filename):
|
|
# from tests.features.steps.inline_yaml_jinja_coverage_steps import TestContext
|
|
# context.test_context = TestContext()
|
|
|
|
|
|
def after_scenario(context, scenario):
|
|
"""Clean up after each scenario."""
|
|
# Clean up bridge resources if present
|
|
if hasattr(context, "bridge") and context.bridge:
|
|
try:
|
|
context.bridge.cleanup()
|
|
except Exception:
|
|
pass
|
|
|
|
# Dispose of app if created
|
|
if hasattr(context, "app") and context.app:
|
|
try:
|
|
# dispose() is async, so we need to run it in the event loop
|
|
if hasattr(context, "loop") and context.loop:
|
|
context.loop.run_until_complete(context.app.dispose())
|
|
else:
|
|
asyncio.run(context.app.dispose())
|
|
except Exception:
|
|
pass
|
|
|
|
# Cancel any remaining tasks without waiting
|
|
if hasattr(context, "loop"):
|
|
try:
|
|
pending = asyncio.all_tasks(context.loop)
|
|
for task in pending:
|
|
task.cancel()
|
|
except Exception:
|
|
pass
|
|
|
|
# Clean up event loops created by LangGraph tests
|
|
if hasattr(context, "event_loops"):
|
|
for loop in context.event_loops:
|
|
try:
|
|
if hasattr(loop, "is_closed") and not loop.is_closed():
|
|
# Cancel all tasks in this loop
|
|
tasks = asyncio.all_tasks(loop)
|
|
for task in tasks:
|
|
task.cancel()
|
|
loop.close()
|
|
except Exception:
|
|
pass
|
|
|
|
# Clean up temp directories from LangGraph tests
|
|
if hasattr(context, "temp_dirs"):
|
|
for temp_dir in context.temp_dirs:
|
|
try:
|
|
shutil.rmtree(temp_dir)
|
|
except:
|
|
pass
|
|
|
|
# Clean up graphs and their schedulers
|
|
if hasattr(context, "graphs"):
|
|
for graph in context.graphs:
|
|
try:
|
|
if hasattr(graph, "scheduler") and hasattr(graph.scheduler, "_loop"):
|
|
loop = graph.scheduler._loop
|
|
if hasattr(loop, "is_closed") and not loop.is_closed():
|
|
# Cancel all tasks
|
|
tasks = asyncio.all_tasks(loop)
|
|
for task in tasks:
|
|
task.cancel()
|
|
loop.close()
|
|
except Exception:
|
|
pass
|
|
|
|
# Clean up template loader test files
|
|
if "template_loaders_coverage" in str(scenario.feature.filename):
|
|
# fmt: off
|
|
from tests.features.steps.template_loaders_coverage_steps import cleanup_test_files # isort: skip
|
|
# fmt: on
|
|
|
|
cleanup_test_files(context)
|
|
|
|
# Clean up files tracked for cleanup in tool_agent tests
|
|
if hasattr(context, "__dict__") and "_cleanup_files" in context.__dict__:
|
|
import os
|
|
|
|
for filepath in context.__dict__["_cleanup_files"]:
|
|
try:
|
|
if os.path.exists(filepath):
|
|
os.remove(filepath)
|
|
except Exception:
|
|
pass
|
|
context.__dict__["_cleanup_files"] = []
|
|
|
|
# Clean up scenario temp directory
|
|
if hasattr(context, "scenario_temp") and context.scenario_temp.exists():
|
|
import shutil
|
|
|
|
try:
|
|
shutil.rmtree(context.scenario_temp, ignore_errors=True)
|
|
except Exception:
|
|
pass
|