Files
placeholder/features/steps/plan_executor_coverage_boost_steps.py
freemo 051ee7c290 test(coverage): add Behave BDD tests to improve coverage across 52 source files
Added 52 new .feature files and corresponding _steps.py files targeting
previously uncovered code paths in the following areas:

- TUI layer: app, commands, persona (state/schema/registry), widgets,
  input (shell_exec, reference_parser)
- Application services: plan lifecycle/service/executor, session,
  project, repo indexing, correction, checkpoint, actor, llm_actors,
  strategy coordinator, resource file watcher, service retry wiring
- CLI commands: session, resource, repl, plan, db, automation_profile
- Domain models: retry_policy, resource_type, cost_budget,
  docker_compose_analyzer, detail_level, _sql_string_aware,
  _postgresql_helpers
- Core: circuit_breaker, retry_service_patterns
- Infrastructure: repositories, transaction_sandbox, strategy_registry,
  plugins/loader, container
- Config: settings
- Agents: plan_generation, context_analysis, auto_debug
- A2A: facade

All new tests follow the Behave/Gherkin BDD standard. Resolved step
definition collisions with unique prefixes. Fixed Alembic fileConfig
logger disabling issue (disable_existing_loggers=False).

ISSUES CLOSED: #1068
2026-03-20 21:22:10 +00:00

348 lines
13 KiB
Python

"""Step definitions for plan_executor_coverage_boost.feature.
These steps target specific uncovered lines in plan_executor.py:
- Lines 328-330: _try_emit_metric success path (emitter configured)
- Lines 331-335: _try_emit_metric exception path (emitter raises)
- Line 384: _try_create_checkpoint returns None (no sandbox)
- Line 422: _try_rollback_to_last_checkpoint returns False (no sandbox)
- Line 458: _resolve_sandbox_for_checkpoint via execution_context
- Lines 598-599: _enforce_guardrails raises PlanError (step limit)
- Line 612: _enforce_guardrails_per_step returns early (guardrails None)
- Line 619: _enforce_guardrails_per_step raises PlanError (wall-clock)
"""
from types import SimpleNamespace
from unittest.mock import MagicMock
from behave import given, then, when
from ulid import ULID
from cleveragents.application.services.autonomy_guardrail_service import (
AutonomyGuardrailService,
)
from cleveragents.application.services.plan_executor import (
PlanExecutor,
)
from cleveragents.core.exceptions import PlanError
from cleveragents.domain.models.core.autonomy_guardrails import AutonomyGuardrails
from cleveragents.domain.models.observability.metrics import OperationalMetricKey
from cleveragents.infrastructure.sandbox.checkpoint import CheckpointManager
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
# A valid 26-char ULID for use as plan_id in metrics and other calls.
_VALID_PLAN_ID = str(ULID())
def _make_lifecycle_stub():
"""Return a minimal mock lifecycle service."""
return MagicMock(name="lifecycle_service")
# ---------------------------------------------------------------------------
# Background
# ---------------------------------------------------------------------------
@given("the plan executor module is imported")
def step_plan_executor_module_imported(context):
"""Verify that PlanExecutor is importable."""
assert PlanExecutor is not None
# ---------------------------------------------------------------------------
# _try_emit_metric success path (lines 328-330)
# ---------------------------------------------------------------------------
@given("a PlanExecutor with a mock metrics emitter")
def step_executor_with_mock_emitter(context):
"""Create a PlanExecutor with a mocked metrics_emitter."""
context.mock_emitter = MagicMock(name="metrics_emitter")
context.executor = PlanExecutor(
lifecycle_service=_make_lifecycle_stub(),
metrics_emitter=context.mock_emitter,
)
@when("I trigger metric emission with a valid key and value")
def step_trigger_metric_emission(context):
"""Call _try_emit_metric with a valid key, plan_id, and value."""
context.emit_error = None
try:
context.executor._try_emit_metric(
key=OperationalMetricKey.PLAN_DURATION_MS,
plan_id=_VALID_PLAN_ID,
value=42.5,
)
except Exception as exc:
context.emit_error = exc
@then("the metrics emitter should have received exactly one entry")
def step_verify_emitter_called(context):
"""Verify the mock emitter's emit() was called once."""
assert context.emit_error is None, f"Unexpected error: {context.emit_error!r}"
assert context.mock_emitter.emit.call_count == 1
# ---------------------------------------------------------------------------
# _try_emit_metric exception path (lines 331-335)
# ---------------------------------------------------------------------------
@given("a PlanExecutor with a failing metrics emitter")
def step_executor_with_failing_emitter(context):
"""Create a PlanExecutor whose emitter.emit() raises."""
failing_emitter = MagicMock(name="failing_emitter")
failing_emitter.emit.side_effect = RuntimeError("emit boom")
context.executor = PlanExecutor(
lifecycle_service=_make_lifecycle_stub(),
metrics_emitter=failing_emitter,
)
@when("I trigger metric emission that causes an exception")
def step_trigger_failing_metric_emission(context):
"""Call _try_emit_metric knowing the emitter will fail."""
context.emit_error = None
try:
context.executor._try_emit_metric(
key=OperationalMetricKey.PLAN_DURATION_MS,
plan_id=_VALID_PLAN_ID,
value=99.0,
)
except Exception as exc:
context.emit_error = exc
@then("no exception should propagate from metric emission")
def step_verify_no_emission_exception(context):
"""Verify the exception was swallowed (best-effort emission)."""
assert context.emit_error is None, f"Expected no error, got {context.emit_error!r}"
# ---------------------------------------------------------------------------
# _try_create_checkpoint returns None when sandbox is None (line 384)
# ---------------------------------------------------------------------------
@given("a PlanExecutor with a checkpoint manager but no sandbox source")
def step_executor_with_checkpoint_manager_no_sandbox(context):
"""Create a PlanExecutor with a checkpoint manager but no sandbox_root
and no execution_context, so _resolve_sandbox_for_checkpoint returns None.
"""
mock_cp_manager = MagicMock(spec=CheckpointManager, name="cp_manager")
context.executor = PlanExecutor(
lifecycle_service=_make_lifecycle_stub(),
checkpoint_manager=mock_cp_manager,
sandbox_root=None,
execution_context=None,
)
@when("I attempt to create a plan executor checkpoint")
def step_attempt_create_checkpoint(context):
"""Call _try_create_checkpoint on the executor."""
context.checkpoint_result = context.executor._try_create_checkpoint(
plan_id=_VALID_PLAN_ID,
phase="pre_execute",
)
@then("the checkpoint result should be None")
def step_verify_checkpoint_none(context):
"""Verify the checkpoint result is None."""
assert context.checkpoint_result is None
# ---------------------------------------------------------------------------
# _try_rollback_to_last_checkpoint returns False (line 422)
# ---------------------------------------------------------------------------
@when("I attempt to rollback to the last checkpoint")
def step_attempt_rollback(context):
"""Call _try_rollback_to_last_checkpoint on the executor."""
context.rollback_result = context.executor._try_rollback_to_last_checkpoint(
plan_id=_VALID_PLAN_ID,
)
@then("the rollback result should be False")
def step_verify_rollback_false(context):
"""Verify the rollback result is False."""
assert context.rollback_result is False
# ---------------------------------------------------------------------------
# _resolve_sandbox_for_checkpoint via execution_context (line 458)
# ---------------------------------------------------------------------------
@given("a PlanExecutor with an execution context that has a sandbox manager")
def step_executor_with_execution_context_sandbox(context):
"""Create a PlanExecutor with an execution_context whose
sandbox_manager.list_sandboxes returns a sandbox object.
"""
mock_sandbox = SimpleNamespace(
sandbox_id="sandbox-from-ctx",
context=SimpleNamespace(sandbox_path="/tmp/sandbox-ctx"),
)
mock_sandbox_mgr = MagicMock(name="sandbox_manager")
mock_sandbox_mgr.list_sandboxes.return_value = [mock_sandbox]
mock_exec_ctx = SimpleNamespace(sandbox_manager=mock_sandbox_mgr)
context.executor = PlanExecutor(
lifecycle_service=_make_lifecycle_stub(),
execution_context=mock_exec_ctx,
)
context.expected_sandbox = mock_sandbox
@when("I resolve a sandbox for checkpointing")
def step_resolve_sandbox(context):
"""Call _resolve_sandbox_for_checkpoint."""
context.resolved_sandbox = context.executor._resolve_sandbox_for_checkpoint(
plan_id=_VALID_PLAN_ID,
)
@then("the resolved sandbox should come from the execution context")
def step_verify_resolved_sandbox(context):
"""Verify the returned sandbox matches the one from the execution context."""
assert context.resolved_sandbox is context.expected_sandbox
assert context.resolved_sandbox.sandbox_id == "sandbox-from-ctx"
# ---------------------------------------------------------------------------
# _enforce_guardrails raises PlanError on step limit (lines 598-599)
# ---------------------------------------------------------------------------
@given("a PlanExecutor with a guardrail service that blocks step limit")
def step_executor_guardrail_blocks_step_limit(context):
"""Create a PlanExecutor with a guardrail service that:
- get_guardrails returns guardrails with start_time already set
- check_wall_clock returns True (ok)
- check_step_limit returns False (blocked)
"""
guardrail_svc = MagicMock(spec=AutonomyGuardrailService, name="guardrail_svc")
mock_guardrails = MagicMock(spec=AutonomyGuardrails)
mock_guardrails.start_time = "2025-01-01T00:00:00Z"
mock_guardrails.step_count = 100
guardrail_svc.get_guardrails.return_value = mock_guardrails
guardrail_svc.check_wall_clock.return_value = True
guardrail_svc.check_step_limit.return_value = False
context.executor = PlanExecutor(
lifecycle_service=_make_lifecycle_stub(),
guardrail_service=guardrail_svc,
)
@when("I enforce guardrails for a plan")
def step_enforce_guardrails(context):
"""Call _enforce_guardrails, expecting a PlanError."""
context.guardrail_error = None
try:
context.executor._enforce_guardrails("plan-step-limit-test")
except PlanError as exc:
context.guardrail_error = exc
@then("a PlanError about step limit should be raised")
def step_verify_step_limit_error(context):
"""Verify that a PlanError mentioning step limit was raised."""
assert context.guardrail_error is not None, "Expected PlanError but none raised"
assert "step limit already reached" in str(context.guardrail_error).lower(), (
f"Unexpected error message: {context.guardrail_error}"
)
# ---------------------------------------------------------------------------
# _enforce_guardrails_per_step returns early when guardrails is None (line 612)
# ---------------------------------------------------------------------------
@given("a PlanExecutor with a guardrail service that returns no guardrails")
def step_executor_guardrail_returns_none(context):
"""Create a PlanExecutor with a guardrail service that returns
None from get_guardrails (no guardrails configured for this plan).
"""
guardrail_svc = MagicMock(spec=AutonomyGuardrailService, name="guardrail_svc_none")
guardrail_svc.get_guardrails.return_value = None
context.executor = PlanExecutor(
lifecycle_service=_make_lifecycle_stub(),
guardrail_service=guardrail_svc,
)
@when("I enforce per-step guardrails")
def step_enforce_per_step_guardrails(context):
"""Call _enforce_guardrails_per_step with guardrails=None."""
context.per_step_error = None
try:
context.executor._enforce_guardrails_per_step("plan-no-guardrails")
except Exception as exc:
context.per_step_error = exc
@then("no exception should be raised from per-step enforcement")
def step_verify_no_per_step_error(context):
"""Verify no exception was raised (early return)."""
assert context.per_step_error is None, (
f"Expected no error, got {context.per_step_error!r}"
)
# ---------------------------------------------------------------------------
# _enforce_guardrails_per_step raises PlanError on wall-clock (line 619)
# ---------------------------------------------------------------------------
@given("a PlanExecutor with a guardrail service that blocks wall-clock per step")
def step_executor_guardrail_blocks_wallclock_per_step(context):
"""Create a PlanExecutor with a guardrail service that:
- get_guardrails returns valid guardrails
- check_step_limit returns True (step OK)
- check_wall_clock returns False (wall-clock exceeded)
"""
guardrail_svc = MagicMock(spec=AutonomyGuardrailService, name="guardrail_svc_wc")
mock_guardrails = MagicMock(spec=AutonomyGuardrails)
mock_guardrails.step_count = 5
guardrail_svc.get_guardrails.return_value = mock_guardrails
guardrail_svc.check_step_limit.return_value = True
guardrail_svc.check_wall_clock.return_value = False
context.executor = PlanExecutor(
lifecycle_service=_make_lifecycle_stub(),
guardrail_service=guardrail_svc,
)
@when("I enforce per-step guardrails expecting wall-clock error")
def step_enforce_per_step_wallclock(context):
"""Call _enforce_guardrails_per_step, expecting a wall-clock PlanError."""
context.per_step_wc_error = None
try:
context.executor._enforce_guardrails_per_step("plan-wc-exceeded")
except PlanError as exc:
context.per_step_wc_error = exc
@then("a PlanError about wall-clock limit should be raised from per-step")
def step_verify_wallclock_per_step_error(context):
"""Verify that a PlanError about wall-clock was raised."""
assert context.per_step_wc_error is not None, "Expected PlanError but none raised"
assert "wall-clock limit exceeded" in str(context.per_step_wc_error).lower(), (
f"Unexpected error message: {context.per_step_wc_error}"
)