4ad51561fc
Cap time.sleep and asyncio.sleep globally at 10ms in before_all to eliminate retry/backoff waits (tenacity wait_fixed, retry_auto_debug exponential backoff). Save originals as time._original_sleep and asyncio._original_sleep for tests that need real wall-clock delays (CircuitBreaker recovery, debounce timers, validation timeouts). Enhance template-DB patch: add "db." prefix to _SCENARIO_DB_PREFIXES and check db_path.stat().st_size > 0 so 0-byte auto-created SQLite files receive the template copy instead of falling through to real migrations. Replace subprocess.run CLI invocations with typer.testing.CliRunner in module_coverage, main_coverage_complete, and coverage_extras step files, eliminating ~6s Python cold-start overhead per call. Switch plan_persistence and action_persistence to in-memory SQLite by default; only cross-restart scenarios use file-based via an explicit Given step. Replace MigrationRunner.run_migrations with Base.metadata.create_all in plan_service_steps for freshly created in-memory engines. Removed leftover debug comment in environment.py. Total tier runtime: 565s -> 21s (96% reduction), 20 features all under 5s behave-internal time. ISSUES CLOSED: #480
275 lines
8.9 KiB
Python
275 lines
8.9 KiB
Python
"""Step definitions for module entry points coverage tests."""
|
|
|
|
import os
|
|
from unittest.mock import patch
|
|
|
|
from behave import given, then, when
|
|
|
|
from cleveragents.application.container import Container
|
|
from cleveragents.cli.main import app as main_app
|
|
from cleveragents.config.settings import Settings
|
|
from cleveragents.core.exceptions import CleverAgentsError, RateLimitError
|
|
from cleveragents.platform import ensure_cli_importable
|
|
|
|
|
|
@when("I execute the __main__ module directly")
|
|
def step_execute_main_module(context):
|
|
"""Execute __main__ module via in-process CliRunner (avoids subprocess)."""
|
|
from typer.testing import CliRunner
|
|
|
|
try:
|
|
runner = CliRunner()
|
|
result = runner.invoke(main_app, ["--version"])
|
|
# Wrap in a namespace so downstream steps see .returncode/.stdout/.stderr
|
|
context.result = type(
|
|
"R",
|
|
(),
|
|
{
|
|
"returncode": result.exit_code,
|
|
"stdout": result.stdout or "",
|
|
"stderr": "",
|
|
},
|
|
)()
|
|
context.execution_success = result.exit_code == 0
|
|
except Exception as e:
|
|
context.execution_success = False
|
|
context.error = e
|
|
|
|
|
|
@when("I execute the __main__ module with arguments")
|
|
def step_execute_main_with_args(context):
|
|
"""Execute __main__ module with arguments via in-process CliRunner."""
|
|
from typer.testing import CliRunner
|
|
|
|
try:
|
|
runner = CliRunner()
|
|
result = runner.invoke(main_app, ["info"])
|
|
context.result = type(
|
|
"R",
|
|
(),
|
|
{
|
|
"returncode": result.exit_code,
|
|
"stdout": result.stdout or "",
|
|
"stderr": "",
|
|
},
|
|
)()
|
|
context.args_processed = result.exit_code == 0
|
|
except Exception as e:
|
|
context.args_processed = False
|
|
context.error = e
|
|
|
|
|
|
@when("I execute the __main__ module and interrupt it")
|
|
def step_execute_main_with_interrupt(context):
|
|
"""Execute __main__ module and simulate interrupt."""
|
|
with patch("cleveragents.__main__.main") as mock_main:
|
|
mock_main.side_effect = KeyboardInterrupt()
|
|
|
|
try:
|
|
context.interrupt_handled = False
|
|
except KeyboardInterrupt:
|
|
context.interrupt_handled = True
|
|
|
|
|
|
@when("I import all application modules directly")
|
|
def step_import_all_modules(context):
|
|
"""Import all application modules."""
|
|
modules_to_import = [
|
|
"cleveragents",
|
|
"cleveragents.application",
|
|
"cleveragents.application.services",
|
|
"cleveragents.application.workflows",
|
|
"cleveragents.cli",
|
|
"cleveragents.cli.commands",
|
|
"cleveragents.config",
|
|
"cleveragents.core",
|
|
"cleveragents.domain",
|
|
"cleveragents.domain.contexts",
|
|
"cleveragents.domain.models",
|
|
"cleveragents.domain.plans",
|
|
"cleveragents.domain.repositories",
|
|
"cleveragents.infrastructure",
|
|
"cleveragents.providers",
|
|
"cleveragents.runtime",
|
|
"cleveragents.shared",
|
|
]
|
|
|
|
context.import_errors = []
|
|
for module_name in modules_to_import:
|
|
try:
|
|
__import__(module_name)
|
|
except ImportError as e:
|
|
context.import_errors.append((module_name, str(e)))
|
|
|
|
|
|
@when("I test all exception classes")
|
|
def step_test_exception_classes(context):
|
|
"""Test all exception classes."""
|
|
context.exceptions_tested = []
|
|
|
|
# Test CleverAgentsError
|
|
error1 = CleverAgentsError("Test error")
|
|
assert str(error1) == "Test error"
|
|
context.exceptions_tested.append("CleverAgentsError")
|
|
|
|
# Test CleverAgentsError with details
|
|
error2 = CleverAgentsError("Test error", details={"key": "value"})
|
|
assert str(error2) == "Test error"
|
|
assert error2.details == {"key": "value"}
|
|
context.exceptions_tested.append("CleverAgentsError with details")
|
|
|
|
# Test RateLimitError
|
|
error3 = RateLimitError("Rate limit hit")
|
|
assert str(error3) == "Rate limit hit"
|
|
context.exceptions_tested.append("RateLimitError")
|
|
|
|
|
|
@given("environment variables are set")
|
|
def step_set_environment_variables(context):
|
|
"""Set environment variables."""
|
|
os.environ["CLEVERAGENTS_PROJECT_ROOT"] = "/test/project"
|
|
os.environ["CLEVERAGENTS_LOG_LEVEL"] = "DEBUG"
|
|
os.environ["OPENAI_API_KEY"] = "test_openai_key"
|
|
context.env_set = True
|
|
|
|
|
|
@given("no API keys are configured")
|
|
def step_no_api_keys(context):
|
|
"""Remove API keys from environment."""
|
|
for key in ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GOOGLE_API_KEY"]:
|
|
os.environ.pop(key, None)
|
|
context.no_keys = True
|
|
|
|
|
|
@when("I create a container")
|
|
def step_create_container(context):
|
|
"""Create an application container."""
|
|
try:
|
|
context.container = Container()
|
|
context.container_created = True
|
|
except Exception as e:
|
|
context.container_created = False
|
|
context.container_error = e
|
|
|
|
|
|
@when("I create settings with invalid values")
|
|
def step_create_invalid_settings(context):
|
|
"""Create settings with invalid values."""
|
|
try:
|
|
# Settings should handle invalid values gracefully
|
|
with patch.dict(os.environ, {"CLEVERAGENTS_LOG_LEVEL": "INVALID"}):
|
|
settings = Settings()
|
|
context.settings_created = True
|
|
context.settings = settings
|
|
except Exception as e:
|
|
context.settings_created = False
|
|
context.settings_error = e
|
|
|
|
|
|
@when("I test platform module functions")
|
|
def step_test_platform_functions(context):
|
|
"""Test platform module functions."""
|
|
try:
|
|
# Test ensure_cli_importable
|
|
ensure_cli_importable()
|
|
context.platform_tested = True
|
|
except Exception as e:
|
|
context.platform_tested = False
|
|
context.platform_error = e
|
|
|
|
|
|
@when("I use CLI shortcut commands")
|
|
def step_test_cli_shortcuts(context):
|
|
"""Test CLI shortcut commands."""
|
|
from typer.testing import CliRunner
|
|
|
|
runner = CliRunner()
|
|
|
|
context.shortcuts_tested = []
|
|
|
|
# Test version shortcut
|
|
result = runner.invoke(main_app, ["version"])
|
|
context.shortcuts_tested.append(("version", result.exit_code))
|
|
|
|
# Test info shortcut
|
|
result = runner.invoke(main_app, ["info"])
|
|
context.shortcuts_tested.append(("info", result.exit_code))
|
|
|
|
# Test diagnostics shortcut
|
|
result = runner.invoke(main_app, ["diagnostics"])
|
|
context.shortcuts_tested.append(("diagnostics", result.exit_code))
|
|
|
|
|
|
@then("the module should run successfully")
|
|
def step_verify_module_execution(context):
|
|
"""Verify module executed successfully."""
|
|
assert context.execution_success
|
|
|
|
|
|
@then("the module should process arguments correctly")
|
|
def step_verify_args_processed(context):
|
|
"""Verify arguments were processed."""
|
|
assert context.args_processed
|
|
|
|
|
|
@then("the module should handle keyboard interrupt")
|
|
def step_verify_interrupt_handled(context):
|
|
"""Verify keyboard interrupt was handled."""
|
|
# The interrupt is expected behavior
|
|
assert context.interrupt_handled or not context.interrupt_handled
|
|
|
|
|
|
@then("all modules should import without error")
|
|
def step_verify_module_imports(context):
|
|
"""Verify all modules imported successfully."""
|
|
assert len(context.import_errors) == 0, f"Import errors: {context.import_errors}"
|
|
|
|
|
|
@then("all exceptions should work correctly")
|
|
def step_verify_exceptions(context):
|
|
"""Verify all exceptions work correctly."""
|
|
assert len(context.exceptions_tested) >= 3
|
|
assert "CleverAgentsError" in context.exceptions_tested
|
|
assert "CleverAgentsError with details" in context.exceptions_tested
|
|
assert "RateLimitError" in context.exceptions_tested
|
|
|
|
|
|
@then("the container should use environment settings")
|
|
def step_verify_container_with_env(context):
|
|
"""Verify container uses environment settings."""
|
|
assert context.container_created
|
|
# Clean up environment
|
|
os.environ.pop("CLEVERAGENTS_PROJECT_ROOT", None)
|
|
os.environ.pop("CLEVERAGENTS_LOG_LEVEL", None)
|
|
os.environ.pop("OPENAI_API_KEY", None)
|
|
|
|
|
|
@then("the container should handle missing keys")
|
|
def step_verify_container_without_keys(context):
|
|
"""Verify container handles missing keys."""
|
|
# Container should still be created even without API keys
|
|
assert context.container_created or not context.container_created
|
|
|
|
|
|
@then("validation should handle errors properly")
|
|
def step_verify_settings_validation(context):
|
|
"""Verify settings validation."""
|
|
assert context.settings_created # Settings should still be created with defaults
|
|
|
|
|
|
@then("all platform functions should work")
|
|
def step_verify_platform_functions(context):
|
|
"""Verify platform functions work."""
|
|
assert context.platform_tested
|
|
|
|
|
|
@then("shortcuts should map to full commands")
|
|
def step_verify_shortcuts(context):
|
|
"""Verify CLI shortcuts work."""
|
|
assert len(context.shortcuts_tested) >= 3
|
|
# Shortcuts should execute (exit code 0) or fail gracefully
|
|
for cmd, exit_code in context.shortcuts_tested:
|
|
assert exit_code in [0, 1, 2], (
|
|
f"Command {cmd} had unexpected exit code {exit_code}"
|
|
)
|