17fe46d925
CI / lint (pull_request) Successful in 18s
CI / typecheck (pull_request) Successful in 26s
CI / security (pull_request) Successful in 17s
CI / quality (pull_request) Successful in 14s
CI / build (pull_request) Successful in 12s
CI / behave (3.13) (pull_request) Failing after 3m50s
CI / docker (pull_request) Has been skipped
CI / helm (pull_request) Has been skipped
CI / coverage (pull_request) Failing after 4m20s
There had been over 100 behave tests failing. There should be none failing now.
187 lines
6.1 KiB
Python
187 lines
6.1 KiB
Python
"""Behave environment setup for feature tests."""
|
|
|
|
import contextlib
|
|
import os
|
|
import shutil
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
LANGSMITH_ENV_VARS = [
|
|
"CLEVERAGENTS_LANGSMITH_ENABLED",
|
|
"CLEVERAGENTS_LANGSMITH_PROJECT",
|
|
"CLEVERAGENTS_LANGSMITH_ENDPOINT",
|
|
"CLEVERAGENTS_LANGSMITH_API_KEY",
|
|
"CLEVERAGENTS_LANGSMITH_TRACING_V2",
|
|
"CLEVERAGENTS_LANGSMITH_USER_ID",
|
|
"LANGCHAIN_TRACING_V2",
|
|
"LANGCHAIN_PROJECT",
|
|
"LANGCHAIN_ENDPOINT",
|
|
"LANGCHAIN_API_KEY",
|
|
"LANGSMITH_PROJECT",
|
|
"LANGSMITH_ENDPOINT",
|
|
"LANGSMITH_API_KEY",
|
|
"LANGSMITH_TRACING_V2",
|
|
"LANGSMITH_USER_ID",
|
|
]
|
|
|
|
|
|
def before_all(context):
|
|
"""Set up test environment before all tests."""
|
|
# Add src to path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
|
|
# Ensure tests never block on migration prompts or real providers
|
|
os.environ.setdefault("CLEVERAGENTS_AUTO_APPLY_MIGRATIONS", "true")
|
|
os.environ.setdefault("CLEVERAGENTS_TESTING_USE_MOCK_AI", "true")
|
|
os.environ.setdefault("CLEVERAGENTS_DATABASE_URL", "sqlite:///cleveragents.db")
|
|
os.environ.setdefault(
|
|
"CLEVERAGENTS_TEST_DATABASE_URL", "sqlite:///cleveragents_test.db"
|
|
)
|
|
os.environ.setdefault("BEHAVE_TESTING", "true")
|
|
|
|
# Set up mock AI provider for all tests
|
|
try:
|
|
from cleveragents.application.container import override_providers
|
|
from features.mocks.mock_ai_provider import MockAIProvider
|
|
|
|
# Override the AI provider with mock for all tests
|
|
mock_provider = MockAIProvider()
|
|
override_providers(ai_provider=mock_provider)
|
|
except ImportError:
|
|
pass # Container not needed for all tests
|
|
|
|
|
|
def before_scenario(context, scenario):
|
|
"""Set up before each scenario."""
|
|
# Store original working directory
|
|
context.original_cwd = os.getcwd()
|
|
|
|
# Initialize cleanup list
|
|
context._cleanup_handlers = []
|
|
context.stubbed_clients = {}
|
|
|
|
# Ensure mock AI flag is always set so plan service tests can resolve actors
|
|
os.environ["CLEVERAGENTS_TESTING_USE_MOCK_AI"] = "true"
|
|
|
|
# Clean up any lingering test environment variables from previous tests
|
|
for env_var in [
|
|
"CLEVERAGENTS_MOCK_SHOULD_FAIL",
|
|
"CLEVERAGENTS_MOCK_INVALID_CODE",
|
|
*LANGSMITH_ENV_VARS,
|
|
]:
|
|
if env_var in os.environ:
|
|
del os.environ[env_var]
|
|
|
|
# Ensure each scenario starts with a fresh database URL so tests
|
|
# don't share persisted project state across runs
|
|
for env_var in ["CLEVERAGENTS_DATABASE_URL", "CLEVERAGENTS_TEST_DATABASE_URL"]:
|
|
os.environ.pop(env_var, None)
|
|
|
|
# Re-apply mock AI provider after container reset
|
|
try:
|
|
from cleveragents.application.container import override_providers
|
|
from features.mocks.mock_ai_provider import MockAIProvider
|
|
|
|
# Override the AI provider with mock for all tests
|
|
mock_provider = MockAIProvider()
|
|
override_providers(ai_provider=mock_provider)
|
|
except ImportError:
|
|
pass # Container not needed for all tests
|
|
|
|
|
|
def after_scenario(context, scenario):
|
|
"""Clean up after each scenario."""
|
|
# Return to original directory first
|
|
if hasattr(context, "original_cwd"):
|
|
os.chdir(context.original_cwd)
|
|
|
|
# Run all cleanup handlers in reverse order
|
|
if hasattr(context, "_cleanup_handlers"):
|
|
for handler in reversed(context._cleanup_handlers):
|
|
with contextlib.suppress(Exception):
|
|
handler()
|
|
context._cleanup_handlers = []
|
|
|
|
# Clean up any test directories
|
|
if hasattr(context, "test_dir") and context.test_dir:
|
|
try:
|
|
if Path(context.test_dir).exists():
|
|
shutil.rmtree(context.test_dir)
|
|
except Exception:
|
|
pass # Ignore cleanup errors
|
|
context.test_dir = None
|
|
|
|
# Clean up environment variables set during tests
|
|
if hasattr(context, "env_vars_to_clean"):
|
|
for key in context.env_vars_to_clean:
|
|
os.environ.pop(key, None)
|
|
context.env_vars_to_clean = []
|
|
|
|
for env_var in [
|
|
*LANGSMITH_ENV_VARS,
|
|
"CLEVERAGENTS_DATABASE_URL",
|
|
"CLEVERAGENTS_TEST_DATABASE_URL",
|
|
]:
|
|
os.environ.pop(env_var, None)
|
|
|
|
# Reset Settings singleton if it was used
|
|
try:
|
|
from cleveragents.config.settings import Settings
|
|
|
|
Settings._instance = None
|
|
except ImportError:
|
|
pass
|
|
|
|
# Reset global container singleton
|
|
try:
|
|
from cleveragents.application.container import reset_container
|
|
|
|
reset_container()
|
|
except ImportError:
|
|
pass
|
|
|
|
# Clean up service instances
|
|
for attr in ["context_service", "plan_service", "project_service"]:
|
|
if hasattr(context, attr):
|
|
delattr(context, attr)
|
|
|
|
# Clean up any remaining attributes that might hold state
|
|
for attr in ["plan", "plans", "project", "changes", "added_files", "all_plans"]:
|
|
if hasattr(context, attr):
|
|
delattr(context, attr)
|
|
|
|
# Restore provider registry env overrides if used in a scenario
|
|
for attr, env_var in [
|
|
("original_provider_env", "CLEVERAGENTS_DEFAULT_PROVIDER"),
|
|
("original_model_env", "CLEVERAGENTS_DEFAULT_MODEL"),
|
|
]:
|
|
if hasattr(context, attr):
|
|
original = getattr(context, attr)
|
|
if original is None:
|
|
os.environ.pop(env_var, None)
|
|
else:
|
|
os.environ[env_var] = original
|
|
delattr(context, attr)
|
|
|
|
# Reset provider registry singleton between scenarios
|
|
try:
|
|
from cleveragents.providers.registry import (
|
|
reset_provider_registry as _reset_registry,
|
|
)
|
|
|
|
_reset_registry()
|
|
except ImportError:
|
|
pass
|
|
|
|
# Clean up in-memory database engine cache to ensure each scenario
|
|
# gets a fresh database. This is critical for tests using :memory: databases
|
|
try:
|
|
from cleveragents.infrastructure.database.engine_cache import MEMORY_ENGINES
|
|
|
|
# Dispose of all cached engines and clear the cache
|
|
for _url, engine in list(MEMORY_ENGINES.items()):
|
|
with contextlib.suppress(Exception):
|
|
engine.dispose()
|
|
MEMORY_ENGINES.clear()
|
|
except ImportError:
|
|
pass
|