forked from HAL9000/cleveragents-core
a808c395f9
Add 53 new .feature files and corresponding step definition files targeting uncovered lines identified in build/coverage.xml. Fix AmbiguousStep conflicts in 7 pre-existing step files by disambiguating step text. New tests cover: ACP clients/facade, actor CLI/config, application container, ACMS service/strategies, async worker, automation profile CLI, autonomy guardrail, bridge, change model, config CLI/service, context service, cross-plan correction, database models, decision service, decomposition clustering/service, discovery handler, langchain chat provider, langgraph nodes, materializers, multi-project service, plan apply/CLI/lifecycle/model/ preflight/resume/service, PostgreSQL analyzer, project CLI/context CLI, provider registry, reactive application/route, repositories, resolver handler, resource registry service, resume model, retry patterns, sandbox protocol, server CLI, skill CLI/service, skills registry, subplan execution/service, system CLI, UKO loader, UoW, and YAML template engine. Closes #645
203 lines
6.8 KiB
Python
203 lines
6.8 KiB
Python
"""Step definitions for Plan Resume Service coverage boost tests.
|
|
|
|
Targets uncovered validation-error branches in PlanResumeService:
|
|
- Line 75: __init__ with None lifecycle_service
|
|
- Line 93: get_resume_metadata with empty plan_id
|
|
- Line 186: build_resume_summary with empty plan_id
|
|
- Line 303: record_step_checkpoint with empty plan_id
|
|
- Line 305: record_step_checkpoint with negative step_index
|
|
- Line 307: record_step_checkpoint with empty decision_id
|
|
- Line 309: record_step_checkpoint with empty step_text
|
|
- Line 354: record_shutdown with empty plan_id
|
|
- Line 384: set_total_steps with negative total
|
|
"""
|
|
|
|
from behave import given, then, when
|
|
from behave.runner import Context
|
|
from ulid import ULID
|
|
|
|
from cleveragents.application.services.plan_lifecycle_service import (
|
|
PlanLifecycleService,
|
|
)
|
|
from cleveragents.application.services.plan_resume_service import (
|
|
PlanResumeService,
|
|
)
|
|
from cleveragents.config.settings import Settings
|
|
from cleveragents.core.exceptions import ValidationError
|
|
from cleveragents.domain.models.core.plan import (
|
|
ProjectLink,
|
|
)
|
|
|
|
# ---- Given steps ----
|
|
|
|
|
|
@given("I have a coverage-boost PlanResumeService")
|
|
def step_create_coverage_boost_service(context: Context) -> None:
|
|
"""Create a lifecycle service and a PlanResumeService for coverage tests."""
|
|
settings = Settings()
|
|
context.cb_lifecycle = PlanLifecycleService(settings=settings)
|
|
context.cb_resume = PlanResumeService(lifecycle_service=context.cb_lifecycle)
|
|
context.cb_error = None
|
|
context.cb_plan_id = None
|
|
|
|
|
|
@given("I have a coverage-boost plan in execute phase")
|
|
def step_create_coverage_boost_plan(context: Context) -> None:
|
|
"""Create a plan in execute/processing state for checkpoint tests."""
|
|
action_name = f"local/cb-test-{ULID()!s}"[:30].lower()
|
|
context.cb_lifecycle.create_action(
|
|
name=action_name,
|
|
description="Coverage boost test action",
|
|
definition_of_done="Step 1\nStep 2",
|
|
strategy_actor="local/stub-strategy",
|
|
execution_actor="local/stub-execute",
|
|
)
|
|
plan = context.cb_lifecycle.use_action(
|
|
action_name=action_name,
|
|
project_links=[ProjectLink(project_name="local/cb-proj")],
|
|
)
|
|
plan_id = plan.identity.plan_id
|
|
|
|
# Advance to execute/processing
|
|
context.cb_lifecycle.start_strategize(plan_id)
|
|
p = context.cb_lifecycle.get_plan(plan_id)
|
|
p.decision_root_id = str(ULID())
|
|
context.cb_lifecycle._commit_plan(p)
|
|
context.cb_lifecycle.complete_strategize(plan_id)
|
|
context.cb_lifecycle.execute_plan(plan_id)
|
|
context.cb_lifecycle.start_execute(plan_id)
|
|
|
|
context.cb_plan_id = plan_id
|
|
|
|
|
|
# ---- When steps ----
|
|
|
|
|
|
@when("I try to create a PlanResumeService with None lifecycle_service")
|
|
def step_create_service_with_none(context: Context) -> None:
|
|
"""Attempt to create PlanResumeService with None."""
|
|
context.cb_error = None
|
|
try:
|
|
PlanResumeService(lifecycle_service=None) # type: ignore[arg-type]
|
|
except ValidationError as exc:
|
|
context.cb_error = exc
|
|
|
|
|
|
@when("I try to get resume metadata with empty plan_id")
|
|
def step_get_metadata_empty_id(context: Context) -> None:
|
|
"""Attempt to get resume metadata with empty string."""
|
|
context.cb_error = None
|
|
try:
|
|
context.cb_resume.get_resume_metadata("")
|
|
except ValidationError as exc:
|
|
context.cb_error = exc
|
|
|
|
|
|
@when("I try to build resume summary with empty plan_id")
|
|
def step_build_summary_empty_id(context: Context) -> None:
|
|
"""Attempt to build resume summary with empty string."""
|
|
context.cb_error = None
|
|
try:
|
|
context.cb_resume.build_resume_summary("")
|
|
except ValidationError as exc:
|
|
context.cb_error = exc
|
|
|
|
|
|
@when("I try to record a step checkpoint with empty plan_id")
|
|
def step_checkpoint_empty_plan_id(context: Context) -> None:
|
|
"""Attempt to record checkpoint with empty plan_id."""
|
|
context.cb_error = None
|
|
try:
|
|
context.cb_resume.record_step_checkpoint(
|
|
plan_id="",
|
|
step_index=0,
|
|
decision_id="DEC001",
|
|
step_text="Do something",
|
|
)
|
|
except ValidationError as exc:
|
|
context.cb_error = exc
|
|
|
|
|
|
@when("I try to record a step checkpoint with step_index {index:d}")
|
|
def step_checkpoint_negative_index(context: Context, index: int) -> None:
|
|
"""Attempt to record checkpoint with given step_index."""
|
|
context.cb_error = None
|
|
try:
|
|
context.cb_resume.record_step_checkpoint(
|
|
plan_id=context.cb_plan_id,
|
|
step_index=index,
|
|
decision_id="DEC001",
|
|
step_text="Do something",
|
|
)
|
|
except ValidationError as exc:
|
|
context.cb_error = exc
|
|
|
|
|
|
@when("I try to record a step checkpoint with empty decision_id")
|
|
def step_checkpoint_empty_decision(context: Context) -> None:
|
|
"""Attempt to record checkpoint with empty decision_id."""
|
|
context.cb_error = None
|
|
try:
|
|
context.cb_resume.record_step_checkpoint(
|
|
plan_id=context.cb_plan_id,
|
|
step_index=0,
|
|
decision_id="",
|
|
step_text="Do something",
|
|
)
|
|
except ValidationError as exc:
|
|
context.cb_error = exc
|
|
|
|
|
|
@when("I try to record a step checkpoint with empty step_text")
|
|
def step_checkpoint_empty_step_text(context: Context) -> None:
|
|
"""Attempt to record checkpoint with empty step_text."""
|
|
context.cb_error = None
|
|
try:
|
|
context.cb_resume.record_step_checkpoint(
|
|
plan_id=context.cb_plan_id,
|
|
step_index=0,
|
|
decision_id="DEC001",
|
|
step_text="",
|
|
)
|
|
except ValidationError as exc:
|
|
context.cb_error = exc
|
|
|
|
|
|
@when("I try to record shutdown with empty plan_id")
|
|
def step_shutdown_empty_plan_id(context: Context) -> None:
|
|
"""Attempt to record shutdown with empty plan_id."""
|
|
context.cb_error = None
|
|
try:
|
|
context.cb_resume.record_shutdown("")
|
|
except ValidationError as exc:
|
|
context.cb_error = exc
|
|
|
|
|
|
@when("I try to set total steps to {total:d}")
|
|
def step_set_total_steps_negative(context: Context, total: int) -> None:
|
|
"""Attempt to set total steps to given value."""
|
|
context.cb_error = None
|
|
try:
|
|
context.cb_resume.set_total_steps(context.cb_plan_id, total)
|
|
except ValidationError as exc:
|
|
context.cb_error = exc
|
|
|
|
|
|
# ---- Then steps ----
|
|
|
|
|
|
@then('a coverage-boost ValidationError should be raised with message "{expected_msg}"')
|
|
def step_assert_validation_error_with_message(
|
|
context: Context, expected_msg: str
|
|
) -> None:
|
|
"""Assert a ValidationError was raised and contains the expected message."""
|
|
assert context.cb_error is not None, (
|
|
"Expected a ValidationError but none was raised"
|
|
)
|
|
assert isinstance(context.cb_error, ValidationError), (
|
|
f"Expected ValidationError, got {type(context.cb_error).__name__}"
|
|
)
|
|
assert expected_msg in str(context.cb_error), (
|
|
f"Expected message containing '{expected_msg}', got: {context.cb_error}"
|
|
)
|